Compare commits

..

1 Commits

Author SHA1 Message Date
The yuzu Community b5784e9af2 Update translations (2020-09-11) 2020-09-11 15:38:10 +00:00
130 changed files with 53095 additions and 1638 deletions
+3
View File
@@ -6,5 +6,8 @@ extraction:
packages:
- "libsdl2-dev"
- "qtmultimedia5-dev"
- "clang-format-10"
- "libtbb-dev"
- "libjack-jackd2-dev"
- "doxygen"
- "graphviz"
+1 -1
View File
@@ -210,7 +210,7 @@ if(ENABLE_QT)
set(QT_PREFIX_HINT)
if(YUZU_USE_BUNDLED_QT)
if ((MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS 1930) AND ARCHITECTURE_x86_64)
set(QT_VER qt-5.12.8-msvc2017_64)
set(QT_VER qt-5.12.0-msvc2017_64)
else()
message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.")
endif()
+4749
View File
File diff suppressed because it is too large Load Diff
+4757
View File
File diff suppressed because it is too large Load Diff
+4732
View File
File diff suppressed because it is too large Load Diff
+4724
View File
File diff suppressed because it is too large Load Diff
+4752
View File
File diff suppressed because it is too large Load Diff
+4719
View File
File diff suppressed because it is too large Load Diff
+4713
View File
File diff suppressed because it is too large Load Diff
+4757
View File
File diff suppressed because it is too large Load Diff
+4725
View File
File diff suppressed because it is too large Load Diff
+4720
View File
File diff suppressed because it is too large Load Diff
+4747
View File
File diff suppressed because it is too large Load Diff
+11 -12
View File
@@ -196,7 +196,7 @@ void CommandGenerator::PreCommand() {
for (std::size_t i = 0; i < splitter_context.GetInfoCount(); i++) {
const auto& base = splitter_context.GetInfo(i);
std::string graph = fmt::format("b[{}]", i);
const auto* head = base.GetHead();
auto* head = base.GetHead();
while (head != nullptr) {
graph += fmt::format("->{}", head->GetMixId());
head = head->GetNextDestination();
@@ -214,7 +214,7 @@ void CommandGenerator::PostCommand() {
void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
s32 channel) {
const auto& in_params = voice_info.GetInParams();
auto& in_params = voice_info.GetInParams();
const auto depop = in_params.should_depop;
if (depop) {
@@ -405,7 +405,7 @@ void CommandGenerator::GenerateBiquadFilterEffectCommand(s32 mix_buffer_offset,
}
void CommandGenerator::GenerateAuxCommand(s32 mix_buffer_offset, EffectBase* info, bool enabled) {
auto* aux = dynamic_cast<EffectAuxInfo*>(info);
auto aux = dynamic_cast<EffectAuxInfo*>(info);
const auto& params = aux->GetParams();
if (aux->GetSendBuffer() != 0 && aux->GetRecvBuffer() != 0) {
const auto max_channels = params.count;
@@ -571,7 +571,7 @@ void CommandGenerator::GenerateSubMixCommand(ServerMixInfo& mix_info) {
if (dumping_frame) {
LOG_DEBUG(Audio, "(DSP_TRACE) GenerateSubMixCommand");
}
const auto& in_params = mix_info.GetInParams();
auto& in_params = mix_info.GetInParams();
GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
in_params.sample_rate);
@@ -650,7 +650,7 @@ void CommandGenerator::GenerateFinalMixCommand() {
LOG_DEBUG(Audio, "(DSP_TRACE) GenerateFinalMixCommand");
}
auto& mix_info = mix_context.GetFinalMixInfo();
const auto& in_params = mix_info.GetInParams();
const auto in_params = mix_info.GetInParams();
GenerateDepopForMixBuffersCommand(in_params.buffer_count, in_params.buffer_offset,
in_params.sample_rate);
@@ -674,7 +674,7 @@ void CommandGenerator::GenerateFinalMixCommand() {
s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
s32 sample_count, s32 channel, std::size_t mix_offset) {
const auto& in_params = voice_info.GetInParams();
auto& in_params = voice_info.GetInParams();
const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
if (wave_buffer.buffer_address == 0) {
return 0;
@@ -714,7 +714,7 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s
s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state,
s32 sample_count, s32 channel, std::size_t mix_offset) {
const auto& in_params = voice_info.GetInParams();
auto& in_params = voice_info.GetInParams();
const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index];
if (wave_buffer.buffer_address == 0) {
return 0;
@@ -766,8 +766,8 @@ s32 CommandGenerator::DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_s
val = std::clamp<s32>(val, -32768, 32767);
// Advance output feedback.
yn2 = yn1;
yn1 = static_cast<s16>(val);
return yn1;
yn1 = val;
return static_cast<s16>(val);
};
std::size_t buffer_offset{};
@@ -853,7 +853,7 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* o
VoiceState& dsp_state, s32 channel,
s32 target_sample_rate, s32 sample_count,
s32 node_id) {
const auto& in_params = voice_info.GetInParams();
auto& in_params = voice_info.GetInParams();
if (dumping_frame) {
LOG_DEBUG(Audio,
"(DSP_TRACE) DecodeFromWaveBuffers, node_id={}, channel={}, "
@@ -867,8 +867,7 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, s32* o
static_cast<float>(in_params.sample_rate) / static_cast<float>(target_sample_rate) *
static_cast<float>(static_cast<s32>(in_params.pitch * 32768.0f)));
auto* output_base = output;
if (dsp_state.fraction + sample_count * resample_rate >
static_cast<s32>(SCALED_MIX_BUFFER_SIZE - 4ULL)) {
if ((dsp_state.fraction + sample_count * resample_rate) > (SCALED_MIX_BUFFER_SIZE - 4ULL)) {
return;
}
+3 -3
View File
@@ -34,7 +34,7 @@ std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigne
CoprocReg CRm, unsigned opc2) {
LOG_CRITICAL(Core_ARM, "CP15: cdp{} p15, {}, {}, {}, {}, {}", two ? "2" : "", opc1, CRd, CRn,
CRm, opc2);
return std::nullopt;
return {};
}
CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
@@ -115,7 +115,7 @@ std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_trans
LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "",
long_transfer ? "l" : "", CRd);
}
return std::nullopt;
return {};
}
std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
@@ -127,7 +127,7 @@ std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_tran
LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "",
long_transfer ? "l" : "", CRd);
}
return std::nullopt;
return {};
}
} // namespace Core
+2 -2
View File
@@ -35,8 +35,8 @@ public:
std::optional<u8> option) override;
ARM_Dynarmic_32& parent;
u32 uprw = 0;
u32 uro = 0;
u32 uprw;
u32 uro;
};
} // namespace Core
+4 -4
View File
@@ -178,7 +178,7 @@ struct System::Impl {
arp_manager.ResetAll();
telemetry_session = std::make_unique<Core::TelemetrySession>();
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
service_manager = std::make_shared<Service::SM::ServiceManager>();
Service::Init(service_manager, system);
GDBStub::DeferStart();
@@ -221,7 +221,7 @@ struct System::Impl {
telemetry_session->AddInitialInfo(*app_loader);
auto main_process =
Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland);
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
const auto [load_result, load_parameters] = app_loader->Load(*main_process);
if (load_result != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
Shutdown();
@@ -629,11 +629,11 @@ Loader::AppLoader& System::GetAppLoader() const {
return *impl->app_loader;
}
void System::SetFilesystem(FileSys::VirtualFilesystem vfs) {
void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
impl->virtual_filesystem = std::move(vfs);
}
FileSys::VirtualFilesystem System::GetFilesystem() const {
std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
return impl->virtual_filesystem;
}
+2 -2
View File
@@ -316,9 +316,9 @@ public:
Service::SM::ServiceManager& ServiceManager();
const Service::SM::ServiceManager& ServiceManager() const;
void SetFilesystem(FileSys::VirtualFilesystem vfs);
void SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs);
FileSys::VirtualFilesystem GetFilesystem() const;
std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
void RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
const std::array<u8, 0x20>& build_id, VAddr main_region_begin,
+4 -3
View File
@@ -23,6 +23,7 @@
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/crypto/aes_util.h"
#include "core/crypto/key_manager.h"
#include "core/crypto/partition_data_manager.h"
@@ -1021,10 +1022,10 @@ void KeyManager::DeriveBase() {
}
}
void KeyManager::DeriveETicket(PartitionDataManager& data,
const FileSys::ContentProvider& provider) {
void KeyManager::DeriveETicket(PartitionDataManager& data) {
// ETicket keys
const auto es = provider.GetEntry(0x0100000000000033, FileSys::ContentRecordType::Program);
const auto es = Core::System::GetInstance().GetContentProvider().GetEntry(
0x0100000000000033, FileSys::ContentRecordType::Program);
if (es == nullptr) {
return;
+1 -5
View File
@@ -20,10 +20,6 @@ namespace Common::FS {
class IOFile;
}
namespace FileSys {
class ContentProvider;
}
namespace Loader {
enum class ResultStatus : u16;
}
@@ -256,7 +252,7 @@ public:
bool BaseDeriveNecessary() const;
void DeriveBase();
void DeriveETicket(PartitionDataManager& data, const FileSys::ContentProvider& provider);
void DeriveETicket(PartitionDataManager& data);
void PopulateTickets();
void SynthesizeTickets();
+5 -5
View File
@@ -4,10 +4,10 @@
#include <fmt/format.h>
#include "common/file_util.h"
#include "core/core.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/vfs.h"
namespace FileSys {
@@ -81,11 +81,11 @@ VirtualDir BISFactory::OpenPartition(BisPartitionId id) const {
}
}
VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id,
VirtualFilesystem file_system) const {
VirtualFile BISFactory::OpenPartitionStorage(BisPartitionId id) const {
auto& keys = Core::Crypto::KeyManager::Instance();
Core::Crypto::PartitionDataManager pdm{file_system->OpenDirectory(
Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), Mode::Read)};
Core::Crypto::PartitionDataManager pdm{
Core::System::GetInstance().GetFilesystem()->OpenDirectory(
Common::FS::GetUserPath(Common::FS::UserPath::SysDataDir), Mode::Read)};
keys.PopulateFromPartitionData(pdm);
switch (id) {
+1 -1
View File
@@ -52,7 +52,7 @@ public:
VirtualDir GetModificationDumpRoot(u64 title_id) const;
VirtualDir OpenPartition(BisPartitionId id) const;
VirtualFile OpenPartitionStorage(BisPartitionId id, VirtualFilesystem file_system) const;
VirtualFile OpenPartitionStorage(BisPartitionId id) const;
VirtualDir GetImageDirectory() const;
+5 -5
View File
@@ -323,7 +323,7 @@ bool NCA::ReadRomFSSection(const NCASectionHeader& section, const NCASectionTabl
subsection_buckets.back().entries.push_back({section.bktr.relocation.offset, {0}, ctr_low});
subsection_buckets.back().entries.push_back({size, {0}, 0});
std::optional<Core::Crypto::Key128> key;
std::optional<Core::Crypto::Key128> key = {};
if (encrypted) {
if (has_rights_id) {
status = Loader::ResultStatus::Success;
@@ -442,18 +442,18 @@ std::optional<Core::Crypto::Key128> NCA::GetTitlekey() {
memcpy(rights_id.data(), header.rights_id.data(), 16);
if (rights_id == u128{}) {
status = Loader::ResultStatus::ErrorInvalidRightsID;
return std::nullopt;
return {};
}
auto titlekey = keys.GetKey(Core::Crypto::S128KeyType::Titlekey, rights_id[1], rights_id[0]);
if (titlekey == Core::Crypto::Key128{}) {
status = Loader::ResultStatus::ErrorMissingTitlekey;
return std::nullopt;
return {};
}
if (!keys.HasKey(Core::Crypto::S128KeyType::Titlekek, master_key_id)) {
status = Loader::ResultStatus::ErrorMissingTitlekek;
return std::nullopt;
return {};
}
Core::Crypto::AESCipher<Core::Crypto::Key128> cipher(
@@ -477,7 +477,7 @@ VirtualFile NCA::Decrypt(const NCASectionHeader& s_header, VirtualFile in, u64 s
case NCASectionCryptoType::BKTR:
LOG_TRACE(Crypto, "called with mode=CTR, starting_offset={:016X}", starting_offset);
{
std::optional<Core::Crypto::Key128> key;
std::optional<Core::Crypto::Key128> key = {};
if (has_rights_id) {
status = Loader::ResultStatus::Success;
key = GetTitlekey();
+1 -1
View File
@@ -83,7 +83,7 @@ enum class Language : u8 {
Italian = 7,
Dutch = 8,
CanadianFrench = 9,
Portuguese = 10,
Portugese = 10,
Russian = 11,
Korean = 12,
Taiwanese = 13,
+2 -4
View File
@@ -245,11 +245,9 @@ void IPSwitchCompiler::Parse() {
// Read rest of patch
while (true) {
if (i + 1 >= lines.size()) {
if (i + 1 >= lines.size())
break;
}
const auto& patch_line = lines[++i];
const auto patch_line = lines[++i];
// Start of new patch
if (StartsWith(patch_line, "@enabled") || StartsWith(patch_line, "@disabled")) {
+40 -43
View File
@@ -12,49 +12,6 @@
#include "core/file_sys/nca_patch.h"
namespace FileSys {
namespace {
template <bool Subsection, typename BlockType, typename BucketType>
std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, const BlockType& block,
const BucketType& buckets) {
if constexpr (Subsection) {
const auto& last_bucket = buckets[block.number_buckets - 1];
if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch) {
return {block.number_buckets - 1, last_bucket.number_entries};
}
} else {
ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block.");
}
std::size_t bucket_id = std::count_if(
block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets,
[&offset](u64 base_offset) { return base_offset <= offset; });
const auto& bucket = buckets[bucket_id];
if (bucket.number_entries == 1) {
return {bucket_id, 0};
}
std::size_t low = 0;
std::size_t mid = 0;
std::size_t high = bucket.number_entries - 1;
while (low <= high) {
mid = (low + high) / 2;
if (bucket.entries[mid].address_patch > offset) {
high = mid - 1;
} else {
if (mid == bucket.number_entries - 1 ||
bucket.entries[mid + 1].address_patch > offset) {
return {bucket_id, mid};
}
low = mid + 1;
}
}
UNREACHABLE_MSG("Offset could not be found in BKTR block.");
}
} // Anonymous namespace
BKTR::BKTR(VirtualFile base_romfs_, VirtualFile bktr_romfs_, RelocationBlock relocation_,
std::vector<RelocationBucket> relocation_buckets_, SubsectionBlock subsection_,
@@ -153,6 +110,46 @@ std::size_t BKTR::Read(u8* data, std::size_t length, std::size_t offset) const {
return raw_read;
}
template <bool Subsection, typename BlockType, typename BucketType>
std::pair<std::size_t, std::size_t> BKTR::SearchBucketEntry(u64 offset, BlockType block,
BucketType buckets) const {
if constexpr (Subsection) {
const auto last_bucket = buckets[block.number_buckets - 1];
if (offset >= last_bucket.entries[last_bucket.number_entries].address_patch)
return {block.number_buckets - 1, last_bucket.number_entries};
} else {
ASSERT_MSG(offset <= block.size, "Offset is out of bounds in BKTR relocation block.");
}
std::size_t bucket_id = std::count_if(
block.base_offsets.begin() + 1, block.base_offsets.begin() + block.number_buckets,
[&offset](u64 base_offset) { return base_offset <= offset; });
const auto bucket = buckets[bucket_id];
if (bucket.number_entries == 1)
return {bucket_id, 0};
std::size_t low = 0;
std::size_t mid = 0;
std::size_t high = bucket.number_entries - 1;
while (low <= high) {
mid = (low + high) / 2;
if (bucket.entries[mid].address_patch > offset) {
high = mid - 1;
} else {
if (mid == bucket.number_entries - 1 ||
bucket.entries[mid + 1].address_patch > offset) {
return {bucket_id, mid};
}
low = mid + 1;
}
}
UNREACHABLE_MSG("Offset could not be found in BKTR block.");
}
RelocationEntry BKTR::GetRelocationEntry(u64 offset) const {
const auto res = SearchBucketEntry<false>(offset, relocation, relocation_buckets);
return relocation_buckets[res.first].entries[res.second];
+4
View File
@@ -117,6 +117,10 @@ public:
bool Rename(std::string_view name) override;
private:
template <bool Subsection, typename BlockType, typename BucketType>
std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, BlockType block,
BucketType buckets) const;
RelocationEntry GetRelocationEntry(u64 offset) const;
RelocationEntry GetNextRelocationEntry(u64 offset) const;
+63 -75
View File
@@ -27,7 +27,6 @@
#include "core/settings.h"
namespace FileSys {
namespace {
constexpr u64 SINGLE_BYTE_MODULUS = 0x100;
constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
@@ -37,28 +36,19 @@ constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{
"subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "subsdk8", "subsdk9",
};
enum class TitleVersionFormat : u8 {
ThreeElements, ///< vX.Y.Z
FourElements, ///< vX.Y.Z.W
};
std::string FormatTitleVersion(u32 version,
TitleVersionFormat format = TitleVersionFormat::ThreeElements) {
std::string FormatTitleVersion(u32 version, TitleVersionFormat format) {
std::array<u8, sizeof(u32)> bytes{};
bytes[0] = static_cast<u8>(version % SINGLE_BYTE_MODULUS);
bytes[0] = version % SINGLE_BYTE_MODULUS;
for (std::size_t i = 1; i < bytes.size(); ++i) {
version /= SINGLE_BYTE_MODULUS;
bytes[i] = static_cast<u8>(version % SINGLE_BYTE_MODULUS);
bytes[i] = version % SINGLE_BYTE_MODULUS;
}
if (format == TitleVersionFormat::FourElements) {
if (format == TitleVersionFormat::FourElements)
return fmt::format("v{}.{}.{}.{}", bytes[3], bytes[2], bytes[1], bytes[0]);
}
return fmt::format("v{}.{}.{}", bytes[3], bytes[2], bytes[1]);
}
// Returns a directory with name matching name case-insensitive. Returns nullptr if directory
// doesn't have a directory with name.
VirtualDir FindSubdirectoryCaseless(const VirtualDir dir, std::string_view name) {
#ifdef _WIN32
return dir->GetSubdirectory(name);
@@ -75,43 +65,6 @@ VirtualDir FindSubdirectoryCaseless(const VirtualDir dir, std::string_view name)
#endif
}
std::optional<std::vector<Core::Memory::CheatEntry>> ReadCheatFileFromFolder(
u64 title_id, const PatchManager::BuildID& build_id_, const VirtualDir& base_path, bool upper) {
const auto build_id_raw = Common::HexToString(build_id_, upper);
const auto build_id = build_id_raw.substr(0, sizeof(u64) * 2);
const auto file = base_path->GetFile(fmt::format("{}.txt", build_id));
if (file == nullptr) {
LOG_INFO(Common_Filesystem, "No cheats file found for title_id={:016X}, build_id={}",
title_id, build_id);
return std::nullopt;
}
std::vector<u8> data(file->GetSize());
if (file->Read(data.data(), data.size()) != data.size()) {
LOG_INFO(Common_Filesystem, "Failed to read cheats file for title_id={:016X}, build_id={}",
title_id, build_id);
return std::nullopt;
}
const Core::Memory::TextCheatParser parser;
return parser.Parse(std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
}
void AppendCommaIfNotEmpty(std::string& to, std::string_view with) {
if (to.empty()) {
to += with;
} else {
to += ", ";
to += with;
}
}
bool IsDirValidAndNonEmpty(const VirtualDir& dir) {
return dir != nullptr && (!dir->GetFiles().empty() || !dir->GetSubdirectories().empty());
}
} // Anonymous namespace
PatchManager::PatchManager(u64 title_id) : title_id(title_id) {}
PatchManager::~PatchManager() = default;
@@ -292,7 +245,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
return out;
}
bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const {
const auto build_id_raw = Common::HexToString(build_id_);
const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
@@ -312,8 +265,36 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
return !CollectPatches(patch_dirs, build_id).empty();
}
namespace {
std::optional<std::vector<Core::Memory::CheatEntry>> ReadCheatFileFromFolder(
const Core::System& system, u64 title_id, const std::array<u8, 0x20>& build_id_,
const VirtualDir& base_path, bool upper) {
const auto build_id_raw = Common::HexToString(build_id_, upper);
const auto build_id = build_id_raw.substr(0, sizeof(u64) * 2);
const auto file = base_path->GetFile(fmt::format("{}.txt", build_id));
if (file == nullptr) {
LOG_INFO(Common_Filesystem, "No cheats file found for title_id={:016X}, build_id={}",
title_id, build_id);
return std::nullopt;
}
std::vector<u8> data(file->GetSize());
if (file->Read(data.data(), data.size()) != data.size()) {
LOG_INFO(Common_Filesystem, "Failed to read cheats file for title_id={:016X}, build_id={}",
title_id, build_id);
return std::nullopt;
}
Core::Memory::TextCheatParser parser;
return parser.Parse(system,
std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
}
} // Anonymous namespace
std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
const Core::System& system, const BuildID& build_id_) const {
const Core::System& system, const std::array<u8, 32>& build_id_) const {
const auto load_dir = system.GetFileSystemController().GetModificationLoadRoot(title_id);
if (load_dir == nullptr) {
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
@@ -333,12 +314,14 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
auto cheats_dir = FindSubdirectoryCaseless(subdir, "cheats");
if (cheats_dir != nullptr) {
if (const auto res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, true)) {
auto res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, true);
if (res.has_value()) {
std::copy(res->begin(), res->end(), std::back_inserter(out));
continue;
}
if (const auto res = ReadCheatFileFromFolder(title_id, build_id_, cheats_dir, false)) {
res = ReadCheatFileFromFolder(system, title_id, build_id_, cheats_dir, false);
if (res.has_value()) {
std::copy(res->begin(), res->end(), std::back_inserter(out));
}
}
@@ -452,11 +435,21 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
return romfs;
}
PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile update_raw) const {
if (title_id == 0) {
return {};
}
static void AppendCommaIfNotEmpty(std::string& to, const std::string& with) {
if (to.empty())
to += with;
else
to += ", " + with;
}
static bool IsDirValidAndNonEmpty(const VirtualDir& dir) {
return dir != nullptr && (!dir->GetFiles().empty() || !dir->GetSubdirectories().empty());
}
std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNames(
VirtualFile update_raw) const {
if (title_id == 0)
return {};
std::map<std::string, std::string, std::less<>> out;
const auto& installed = Core::System::GetInstance().GetContentProvider();
const auto& disabled = Settings::values.disabled_addons[title_id];
@@ -479,7 +472,8 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
if (meta_ver.value_or(0) == 0) {
out.insert_or_assign(update_label, "");
} else {
out.insert_or_assign(update_label, FormatTitleVersion(*meta_ver));
out.insert_or_assign(
update_label, FormatTitleVersion(*meta_ver, TitleVersionFormat::ThreeElements));
}
} else if (update_raw != nullptr) {
out.insert_or_assign(update_label, "PACKED");
@@ -568,46 +562,40 @@ std::optional<u32> PatchManager::GetGameVersion() const {
return installed.GetEntryVersion(title_id);
}
PatchManager::Metadata PatchManager::GetControlMetadata() const {
std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const {
const auto& installed = Core::System::GetInstance().GetContentProvider();
const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control);
if (base_control_nca == nullptr) {
if (base_control_nca == nullptr)
return {};
}
return ParseControlNCA(*base_control_nca);
}
PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const {
std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::ParseControlNCA(const NCA& nca) const {
const auto base_romfs = nca.GetRomFS();
if (base_romfs == nullptr) {
if (base_romfs == nullptr)
return {};
}
const auto romfs = PatchRomFS(base_romfs, nca.GetBaseIVFCOffset(), ContentRecordType::Control);
if (romfs == nullptr) {
if (romfs == nullptr)
return {};
}
const auto extracted = ExtractRomFS(romfs);
if (extracted == nullptr) {
if (extracted == nullptr)
return {};
}
auto nacp_file = extracted->GetFile("control.nacp");
if (nacp_file == nullptr) {
if (nacp_file == nullptr)
nacp_file = extracted->GetFile("Control.nacp");
}
auto nacp = nacp_file == nullptr ? nullptr : std::make_unique<NACP>(nacp_file);
VirtualFile icon_file;
for (const auto& language : FileSys::LANGUAGE_NAMES) {
icon_file = extracted->GetFile(std::string("icon_").append(language).append(".dat"));
if (icon_file != nullptr) {
icon_file = extracted->GetFile("icon_" + std::string(language) + ".dat");
if (icon_file != nullptr)
break;
}
}
return {std::move(nacp), icon_file};
+28 -20
View File
@@ -22,62 +22,70 @@ namespace FileSys {
class NCA;
class NACP;
enum class TitleVersionFormat : u8 {
ThreeElements, ///< vX.Y.Z
FourElements, ///< vX.Y.Z.W
};
std::string FormatTitleVersion(u32 version,
TitleVersionFormat format = TitleVersionFormat::ThreeElements);
// Returns a directory with name matching name case-insensitive. Returns nullptr if directory
// doesn't have a directory with name.
VirtualDir FindSubdirectoryCaseless(VirtualDir dir, std::string_view name);
// A centralized class to manage patches to games.
class PatchManager {
public:
using BuildID = std::array<u8, 0x20>;
using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>;
using PatchVersionNames = std::map<std::string, std::string, std::less<>>;
explicit PatchManager(u64 title_id);
~PatchManager();
[[nodiscard]] u64 GetTitleID() const;
u64 GetTitleID() const;
// Currently tracked ExeFS patches:
// - Game Updates
[[nodiscard]] VirtualDir PatchExeFS(VirtualDir exefs) const;
VirtualDir PatchExeFS(VirtualDir exefs) const;
// Currently tracked NSO patches:
// - IPS
// - IPSwitch
[[nodiscard]] std::vector<u8> PatchNSO(const std::vector<u8>& nso,
const std::string& name) const;
std::vector<u8> PatchNSO(const std::vector<u8>& nso, const std::string& name) const;
// Checks to see if PatchNSO() will have any effect given the NSO's build ID.
// Used to prevent expensive copies in NSO loader.
[[nodiscard]] bool HasNSOPatch(const BuildID& build_id) const;
bool HasNSOPatch(const std::array<u8, 0x20>& build_id) const;
// Creates a CheatList object with all
[[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList(
const Core::System& system, const BuildID& build_id) const;
std::vector<Core::Memory::CheatEntry> CreateCheatList(
const Core::System& system, const std::array<u8, 0x20>& build_id) const;
// Currently tracked RomFS patches:
// - Game Updates
// - LayeredFS
[[nodiscard]] VirtualFile PatchRomFS(VirtualFile base, u64 ivfc_offset,
ContentRecordType type = ContentRecordType::Program,
VirtualFile update_raw = nullptr) const;
VirtualFile PatchRomFS(VirtualFile base, u64 ivfc_offset,
ContentRecordType type = ContentRecordType::Program,
VirtualFile update_raw = nullptr) const;
// Returns a vector of pairs between patch names and patch versions.
// i.e. Update 3.2.2 will return {"Update", "3.2.2"}
[[nodiscard]] PatchVersionNames GetPatchVersionNames(VirtualFile update_raw = nullptr) const;
std::map<std::string, std::string, std::less<>> GetPatchVersionNames(
VirtualFile update_raw = nullptr) const;
// If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails,
// it will fallback to the Meta-type NCA of the base game. If that fails, the result will be
// std::nullopt
[[nodiscard]] std::optional<u32> GetGameVersion() const;
std::optional<u32> GetGameVersion() const;
// Given title_id of the program, attempts to get the control data of the update and parse
// it, falling back to the base control data.
[[nodiscard]] Metadata GetControlMetadata() const;
std::pair<std::unique_ptr<NACP>, VirtualFile> GetControlMetadata() const;
// Version of GetControlMetadata that takes an arbitrary NCA
[[nodiscard]] Metadata ParseControlNCA(const NCA& nca) const;
std::pair<std::unique_ptr<NACP>, VirtualFile> ParseControlNCA(const NCA& nca) const;
private:
[[nodiscard]] std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
const std::string& build_id) const;
std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
const std::string& build_id) const;
u64 title_id;
};
+25 -25
View File
@@ -6,6 +6,7 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/nca_metadata.h"
@@ -18,9 +19,7 @@
namespace FileSys {
RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader, ContentProvider& provider,
Service::FileSystem::FileSystemController& controller)
: content_provider{provider}, filesystem_controller{controller} {
RomFSFactory::RomFSFactory(Loader::AppLoader& app_loader) {
// Load the RomFS from the app
if (app_loader.ReadRomFS(file) != Loader::ResultStatus::Success) {
LOG_ERROR(Service_FS, "Unable to read RomFS!");
@@ -47,38 +46,39 @@ ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_titl
ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage,
ContentRecordType type) const {
const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type);
std::shared_ptr<NCA> res;
switch (storage) {
case StorageId::None:
res = Core::System::GetInstance().GetContentProvider().GetEntry(title_id, type);
break;
case StorageId::NandSystem:
res =
Core::System::GetInstance().GetFileSystemController().GetSystemNANDContents()->GetEntry(
title_id, type);
break;
case StorageId::NandUser:
res = Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->GetEntry(
title_id, type);
break;
case StorageId::SdCard:
res = Core::System::GetInstance().GetFileSystemController().GetSDMCContents()->GetEntry(
title_id, type);
break;
default:
UNIMPLEMENTED_MSG("Unimplemented storage_id={:02X}", static_cast<u8>(storage));
}
if (res == nullptr) {
// TODO(DarkLordZach): Find the right error code to use here
return RESULT_UNKNOWN;
}
const auto romfs = res->GetRomFS();
if (romfs == nullptr) {
// TODO(DarkLordZach): Find the right error code to use here
return RESULT_UNKNOWN;
}
return MakeResult<VirtualFile>(romfs);
}
std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage,
ContentRecordType type) const {
switch (storage) {
case StorageId::None:
return content_provider.GetEntry(title_id, type);
case StorageId::NandSystem:
return filesystem_controller.GetSystemNANDContents()->GetEntry(title_id, type);
case StorageId::NandUser:
return filesystem_controller.GetUserNANDContents()->GetEntry(title_id, type);
case StorageId::SdCard:
return filesystem_controller.GetSDMCContents()->GetEntry(title_id, type);
case StorageId::Host:
case StorageId::GameCard:
default:
UNIMPLEMENTED_MSG("Unimplemented storage_id={:02X}", static_cast<u8>(storage));
return nullptr;
}
}
} // namespace FileSys
+3 -18
View File
@@ -13,15 +13,8 @@ namespace Loader {
class AppLoader;
} // namespace Loader
namespace Service::FileSystem {
class FileSystemController;
}
namespace FileSys {
class ContentProvider;
class NCA;
enum class ContentRecordType : u8;
enum class StorageId : u8 {
@@ -36,26 +29,18 @@ enum class StorageId : u8 {
/// File system interface to the RomFS archive
class RomFSFactory {
public:
explicit RomFSFactory(Loader::AppLoader& app_loader, ContentProvider& provider,
Service::FileSystem::FileSystemController& controller);
explicit RomFSFactory(Loader::AppLoader& app_loader);
~RomFSFactory();
void SetPackedUpdate(VirtualFile update_raw);
[[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
[[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage,
ContentRecordType type) const;
ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
ResultVal<VirtualFile> Open(u64 title_id, StorageId storage, ContentRecordType type) const;
private:
[[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage,
ContentRecordType type) const;
VirtualFile file;
VirtualFile update_raw;
bool updatable;
u64 ivfc_offset;
ContentProvider& content_provider;
Service::FileSystem::FileSystemController& filesystem_controller;
};
} // namespace FileSys
+5 -5
View File
@@ -267,9 +267,9 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
}
const CNMT cnmt(inner_file);
auto& ncas_title = ncas[cnmt.GetTitleID()];
ncas[cnmt.GetTitleID()][{cnmt.GetType(), ContentRecordType::Meta}] = nca;
ncas_title[{cnmt.GetType(), ContentRecordType::Meta}] = nca;
for (const auto& rec : cnmt.GetContentRecords()) {
const auto id_string = Common::HexToString(rec.nca_id, false);
auto next_file = pfs->GetFile(fmt::format("{}.nca", id_string));
@@ -287,12 +287,12 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
auto next_nca = std::make_shared<NCA>(std::move(next_file), nullptr, 0);
if (next_nca->GetType() == NCAContentType::Program) {
program_status[next_nca->GetTitleId()] = next_nca->GetStatus();
program_status[cnmt.GetTitleID()] = next_nca->GetStatus();
}
if (next_nca->GetStatus() == Loader::ResultStatus::Success ||
(next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS &&
(next_nca->GetTitleId() & 0x800) != 0)) {
ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] = std::move(next_nca);
(cnmt.GetTitleID() & 0x800) != 0)) {
ncas_title[{cnmt.GetType(), rec.type}] = std::move(next_nca);
}
}
+3 -4
View File
@@ -169,12 +169,11 @@ VfsDirectory::~VfsDirectory() = default;
std::optional<u8> VfsFile::ReadByte(std::size_t offset) const {
u8 out{};
const std::size_t size = Read(&out, sizeof(u8), offset);
if (size == 1) {
std::size_t size = Read(&out, 1, offset);
if (size == 1)
return out;
}
return std::nullopt;
return {};
}
std::vector<u8> VfsFile::ReadBytes(std::size_t size, std::size_t offset) const {
+3 -4
View File
@@ -58,11 +58,10 @@ std::size_t OffsetVfsFile::Write(const u8* data, std::size_t length, std::size_t
}
std::optional<u8> OffsetVfsFile::ReadByte(std::size_t r_offset) const {
if (r_offset >= size) {
return std::nullopt;
}
if (r_offset < size)
return file->ReadByte(offset + r_offset);
return file->ReadByte(offset + r_offset);
return {};
}
std::vector<u8> OffsetVfsFile::ReadBytes(std::size_t r_size, std::size_t r_offset) const {
+3 -5
View File
@@ -54,11 +54,9 @@ public:
}
std::optional<u8> ReadByte(std::size_t offset) const override {
if (offset >= size) {
return std::nullopt;
}
return value;
if (offset < size)
return value;
return {};
}
std::vector<u8> ReadBytes(std::size_t length, std::size_t offset) const override {
+4 -18
View File
@@ -119,11 +119,11 @@ using ButtonDevice = InputDevice<bool>;
using AnalogDevice = InputDevice<std::tuple<float, float>>;
/**
* A motion status is an object that returns a tuple of accelerometer state vector,
* gyroscope state vector, rotation state vector and orientation state matrix.
* A motion device is an input device that returns a tuple of accelerometer state vector and
* gyroscope state vector.
*
* For both vectors:
* x+ is the same direction as RIGHT on D-pad.
* x+ is the same direction as LEFT on D-pad.
* y+ is normal to the touch screen, pointing outward.
* z+ is the same direction as UP on D-pad.
*
@@ -133,22 +133,8 @@ using AnalogDevice = InputDevice<std::tuple<float, float>>;
* For gyroscope state vector:
* Orientation is determined by right-hand rule.
* Units: deg/sec
*
* For rotation state vector
* Units: rotations
*
* For orientation state matrix
* x vector
* y vector
* z vector
*/
using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common::Vec3<float>,
std::array<Common::Vec3f, 3>>;
/**
* A motion device is an input device that returns a motion status object
*/
using MotionDevice = InputDevice<MotionStatus>;
using MotionDevice = InputDevice<std::tuple<Common::Vec3<float>, Common::Vec3<float>>>;
/**
* A touch device is an input device that returns a tuple of two floats and a bool. The floats are
+2 -3
View File
@@ -48,15 +48,14 @@ ResultVal<std::shared_ptr<ClientSession>> ClientSession::Create(KernelCore& kern
}
ResultCode ClientSession::SendSyncRequest(std::shared_ptr<Thread> thread,
Core::Memory::Memory& memory,
Core::Timing::CoreTiming& core_timing) {
Core::Memory::Memory& memory) {
// Keep ServerSession alive until we're done working with it.
if (!parent->Server()) {
return ERR_SESSION_CLOSED_BY_REMOTE;
}
// Signal the server session that new data is available
return parent->Server()->HandleSyncRequest(std::move(thread), memory, core_timing);
return parent->Server()->HandleSyncRequest(std::move(thread), memory);
}
} // namespace Kernel
+1 -6
View File
@@ -16,10 +16,6 @@ namespace Core::Memory {
class Memory;
}
namespace Core::Timing {
class CoreTiming;
}
namespace Kernel {
class KernelCore;
@@ -46,8 +42,7 @@ public:
return HANDLE_TYPE;
}
ResultCode SendSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory,
Core::Timing::CoreTiming& core_timing);
ResultCode SendSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory);
bool ShouldWait(const Thread* thread) const override;
+1 -1
View File
@@ -188,7 +188,7 @@ private:
/// Scheduler lock mechanisms.
bool is_locked{};
std::mutex inner_lock;
Common::SpinLock inner_lock{};
std::atomic<s64> scope_lock{};
Core::EmuThreadHandle current_owner{Core::EmuThreadHandle::InvalidHandle()};
+3 -3
View File
@@ -8,6 +8,7 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
@@ -184,11 +185,10 @@ ResultCode ServerSession::CompleteSyncRequest() {
}
ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
Core::Memory::Memory& memory,
Core::Timing::CoreTiming& core_timing) {
Core::Memory::Memory& memory) {
const ResultCode result = QueueSyncRequest(std::move(thread), memory);
const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000};
core_timing.ScheduleEvent(delay, request_event, {});
Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {});
return result;
}
+4 -7
View File
@@ -18,9 +18,8 @@ class Memory;
}
namespace Core::Timing {
class CoreTiming;
struct EventType;
} // namespace Core::Timing
}
namespace Kernel {
@@ -88,14 +87,12 @@ public:
/**
* Handle a sync request from the emulated application.
*
* @param thread Thread that initiated the request.
* @param memory Memory context to handle the sync request under.
* @param core_timing Core timing context to schedule the request event under.
* @param thread Thread that initiated the request.
* @param memory Memory context to handle the sync request under.
*
* @returns ResultCode from the operation.
*/
ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory,
Core::Timing::CoreTiming& core_timing);
ResultCode HandleSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory);
bool ShouldWait(const Thread* thread) const override;
+1 -1
View File
@@ -346,7 +346,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
SchedulerLock lock(system.Kernel());
thread->InvalidateHLECallback();
thread->SetStatus(ThreadStatus::WaitIPC);
session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
session->SendSyncRequest(SharedFrom(thread), system.Memory());
}
if (thread->HasHLECallback()) {
+1 -9
View File
@@ -1192,7 +1192,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{120, nullptr, "ExecuteProgram"},
{121, nullptr, "ClearUserChannel"},
{122, nullptr, "UnpopToUserChannel"},
{123, &IApplicationFunctions::GetPreviousProgramIndex, "GetPreviousProgramIndex"},
{123, nullptr, "GetPreviousProgramIndex"},
{124, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
{130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"},
{140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"},
@@ -1554,14 +1554,6 @@ void IApplicationFunctions::QueryApplicationPlayStatisticsByUid(Kernel::HLEReque
rb.Push<u32>(0);
}
void IApplicationFunctions::GetPreviousProgramIndex(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<s32>(previous_program_index);
}
void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
-2
View File
@@ -288,13 +288,11 @@ private:
void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx);
void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx);
void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx);
void GetPreviousProgramIndex(Kernel::HLERequestContext& ctx);
void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx);
bool launch_popped_application_specific = false;
bool launch_popped_account_preselect = false;
s32 previous_program_index{-1};
Kernel::EventPair gpu_error_detected_event;
Kernel::EventPair friend_invitation_storage_channel_event;
Core::System& system;
@@ -379,7 +379,7 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage(
return FileSys::ERROR_ENTITY_NOT_FOUND;
}
auto part = bis_factory->OpenPartitionStorage(id, system.GetFilesystem());
auto part = bis_factory->OpenPartitionStorage(id);
if (part == nullptr) {
return FileSys::ERROR_INVALID_ARGUMENT;
}
@@ -250,9 +250,6 @@ void Controller_NPad::OnLoadInputDevices() {
std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
}
}
@@ -269,7 +266,6 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
const auto& button_state = buttons[controller_idx];
const auto& analog_state = sticks[controller_idx];
const auto& motion_state = motions[controller_idx];
const auto [stick_l_x_f, stick_l_y_f] =
analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
const auto [stick_r_x_f, stick_r_y_f] =
@@ -364,45 +360,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
continue;
}
const u32 npad_index = static_cast<u32>(i);
const std::array<SixAxisGeneric*, 6> controller_sixaxes{
&npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
&npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
};
for (auto* sixaxis_sensor : controller_sixaxes) {
sixaxis_sensor->common.entry_count = 16;
sixaxis_sensor->common.total_entry_count = 17;
const auto& last_entry =
sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks();
sixaxis_sensor->common.last_entry_index =
(sixaxis_sensor->common.last_entry_index + 1) % 17;
auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
cur_entry.timestamp = last_entry.timestamp + 1;
cur_entry.timestamp2 = cur_entry.timestamp;
}
// Try to read sixaxis sensor states
std::array<MotionDevice, 2> motion_devices;
if (sixaxis_sensors_enabled && Settings::values.motion_enabled) {
sixaxis_at_rest = true;
for (std::size_t e = 0; e < motion_devices.size(); ++e) {
const auto& device = motions[i][e];
if (device) {
std::tie(motion_devices[e].accel, motion_devices[e].gyro,
motion_devices[e].rotation, motion_devices[e].orientation) =
device->GetStatus();
sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f;
}
}
}
RequestPadStateUpdate(npad_index);
auto& pad_state = npad_pad_states[npad_index];
@@ -420,18 +377,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
libnx_entry.connection_status.raw = 0;
libnx_entry.connection_status.IsConnected.Assign(1);
auto& full_sixaxis_entry =
npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
auto& handheld_sixaxis_entry =
npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
auto& dual_left_sixaxis_entry =
npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
auto& dual_right_sixaxis_entry =
npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
auto& left_sixaxis_entry =
npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
auto& right_sixaxis_entry =
npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
switch (controller_type) {
case NPadControllerType::None:
@@ -446,13 +391,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
main_controller.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsWired.Assign(1);
if (sixaxis_sensors_enabled && motions[i][0]) {
full_sixaxis_entry.accel = motion_devices[0].accel;
full_sixaxis_entry.gyro = motion_devices[0].gyro;
full_sixaxis_entry.rotation = motion_devices[0].rotation;
full_sixaxis_entry.orientation = motion_devices[0].orientation;
}
break;
case NPadControllerType::Handheld:
handheld_entry.connection_status.raw = 0;
@@ -471,13 +409,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
libnx_entry.connection_status.IsRightJoyWired.Assign(1);
if (sixaxis_sensors_enabled && motions[i][0]) {
handheld_sixaxis_entry.accel = motion_devices[0].accel;
handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
handheld_sixaxis_entry.orientation = motion_devices[0].orientation;
}
break;
case NPadControllerType::JoyDual:
dual_entry.connection_status.raw = 0;
@@ -490,21 +421,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
if (sixaxis_sensors_enabled && motions[i][0]) {
// Set motion for the left joycon
dual_left_sixaxis_entry.accel = motion_devices[0].accel;
dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
dual_left_sixaxis_entry.orientation = motion_devices[0].orientation;
}
if (sixaxis_sensors_enabled && motions[i][1]) {
// Set motion for the right joycon
dual_right_sixaxis_entry.accel = motion_devices[1].accel;
dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
dual_right_sixaxis_entry.orientation = motion_devices[1].orientation;
}
break;
case NPadControllerType::JoyLeft:
left_entry.connection_status.raw = 0;
@@ -515,13 +431,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
left_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
if (sixaxis_sensors_enabled && motions[i][0]) {
left_sixaxis_entry.accel = motion_devices[0].accel;
left_sixaxis_entry.gyro = motion_devices[0].gyro;
left_sixaxis_entry.rotation = motion_devices[0].rotation;
left_sixaxis_entry.orientation = motion_devices[0].orientation;
}
break;
case NPadControllerType::JoyRight:
right_entry.connection_status.raw = 0;
@@ -532,13 +441,6 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
right_entry.pad.r_stick = pad_state.r_stick;
libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
if (sixaxis_sensors_enabled && motions[i][1]) {
right_sixaxis_entry.accel = motion_devices[1].accel;
right_sixaxis_entry.gyro = motion_devices[1].gyro;
right_sixaxis_entry.rotation = motion_devices[1].rotation;
right_sixaxis_entry.orientation = motion_devices[1].orientation;
}
break;
case NPadControllerType::Pokeball:
pokeball_entry.connection_status.raw = 0;
@@ -593,14 +495,6 @@ Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
return hold_type;
}
void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
handheld_activation_mode = activation_mode;
}
Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
return handheld_activation_mode;
}
void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
const std::size_t npad_index = NPadIdToIndex(npad_id);
ASSERT(npad_index < shared_memory_entries.size());
@@ -688,14 +582,6 @@ Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMo
return gyroscope_zero_drift_mode;
}
bool Controller_NPad::IsSixAxisSensorAtRest() const {
return sixaxis_at_rest;
}
void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) {
sixaxis_sensors_enabled = six_axis_status;
}
void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
const auto npad_index_1 = NPadIdToIndex(npad_id_1);
const auto npad_index_2 = NPadIdToIndex(npad_id_2);
+9 -55
View File
@@ -74,12 +74,6 @@ public:
Single = 1,
};
enum class NpadHandheldActivationMode : u64 {
Dual = 0,
Single = 1,
None = 2,
};
enum class NPadControllerType {
None,
ProController,
@@ -116,9 +110,6 @@ public:
void SetHoldType(NpadHoldType joy_hold_type);
NpadHoldType GetHoldType() const;
void SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode);
NpadHandheldActivationMode GetNpadHandheldActivationMode() const;
void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode);
void VibrateController(const std::vector<u32>& controller_ids,
@@ -139,8 +130,6 @@ public:
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode);
GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const;
bool IsSixAxisSensorAtRest() const;
void SetSixAxisEnabled(bool six_axis_status);
LedPattern GetLedPattern(u32 npad_id);
void SetVibrationEnabled(bool can_vibrate);
bool IsVibrationEnabled() const;
@@ -263,24 +252,6 @@ private:
};
static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size");
struct SixAxisStates {
s64_le timestamp{};
INSERT_PADDING_WORDS(2);
s64_le timestamp2{};
Common::Vec3f accel{};
Common::Vec3f gyro{};
Common::Vec3f rotation{};
std::array<Common::Vec3f, 3> orientation{};
s64_le always_one{1};
};
static_assert(sizeof(SixAxisStates) == 0x68, "SixAxisStates is an invalid size");
struct SixAxisGeneric {
CommonHeader common{};
std::array<SixAxisStates, 17> sixaxis{};
};
static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size");
enum class ColorReadError : u32_le {
ReadOk = 0,
ColorDoesntExist = 1,
@@ -310,13 +281,6 @@ private:
};
};
struct MotionDevice {
Common::Vec3f accel;
Common::Vec3f gyro;
Common::Vec3f rotation;
std::array<Common::Vec3f, 3> orientation;
};
struct NPadEntry {
NPadType joy_styles;
NPadAssignments pad_assignment;
@@ -336,12 +300,9 @@ private:
NPadGeneric pokeball_states;
NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be
// relying on this for the time being
SixAxisGeneric sixaxis_full;
SixAxisGeneric sixaxis_handheld;
SixAxisGeneric sixaxis_dual_left;
SixAxisGeneric sixaxis_dual_right;
SixAxisGeneric sixaxis_left;
SixAxisGeneric sixaxis_right;
INSERT_PADDING_BYTES(
0x708 *
6); // TODO(ogniK): SixAxis states, require more information before implementation
NPadDevice device_type;
NPadProperties properties;
INSERT_PADDING_WORDS(1);
@@ -364,29 +325,22 @@ private:
NPadType style{};
std::array<NPadEntry, 10> shared_memory_entries{};
using ButtonArray = std::array<
std::array<
std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>,
10>;
using StickArray = std::array<
10>
buttons;
std::array<
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>,
10>;
using MotionArray = std::array<
std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTION_HID>,
10>;
ButtonArray buttons;
StickArray sticks;
MotionArray motions;
10>
sticks;
std::vector<u32> supported_npad_id_types{};
NpadHoldType hold_type{NpadHoldType::Vertical};
NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
// Each controller should have their own styleset changed event
std::array<Kernel::EventPair, 10> styleset_changed_events;
Vibration last_processed_vibration{};
std::array<ControllerHolder, 10> connected_controllers{};
GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
bool can_controllers_vibrate{true};
bool sixaxis_sensors_enabled{true};
bool sixaxis_at_rest{true};
std::array<ControllerPad, 10> npad_pad_states{};
bool is_in_lr_assignment_mode{false};
Core::System& system;
+12 -42
View File
@@ -40,7 +40,7 @@ namespace Service::HID {
// Updating period for each HID device.
// HID is polled every 15ms, this value was derived from
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering#joy-con-status-data-packet
constexpr auto pad_update_ns = std::chrono::nanoseconds{1000 * 1000}; // (1ms, 1000Hz)
constexpr auto pad_update_ns = std::chrono::nanoseconds{15 * 1000 * 1000}; // (15ms, 66.6Hz)
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
IAppletResource::IAppletResource(Core::System& system)
@@ -164,8 +164,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
{56, nullptr, "ActivateJoyXpad"},
{58, nullptr, "GetJoyXpadLifoHandle"},
{59, nullptr, "GetJoyXpadIds"},
{60, &Hid::ActivateSixAxisSensor, "ActivateSixAxisSensor"},
{61, &Hid::DeactivateSixAxisSensor, "DeactivateSixAxisSensor"},
{60, nullptr, "ActivateSixAxisSensor"},
{61, nullptr, "DeactivateSixAxisSensor"},
{62, nullptr, "GetSixAxisSensorLifoHandle"},
{63, nullptr, "ActivateJoySixAxisSensor"},
{64, nullptr, "DeactivateJoySixAxisSensor"},
@@ -329,31 +329,6 @@ void Hid::GetXpadIDs(Kernel::HLERequestContext& ctx) {
rb.Push(0);
}
void Hid::ActivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto handle{rp.Pop<u32>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(true);
LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle,
applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Hid::DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto handle{rp.Pop<u32>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad).SetSixAxisEnabled(false);
LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle,
applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void Hid::ActivateDebugPad(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
@@ -509,13 +484,13 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
const auto handle{rp.Pop<u32>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle,
applet_resource_user_id);
LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
.IsSixAxisSensorAtRest());
// TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
rb.Push(true);
}
void Hid::SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
@@ -739,11 +714,8 @@ void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
const auto applet_resource_user_id{rp.Pop<u64>()};
const auto mode{rp.Pop<u64>()};
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, mode={}", applet_resource_user_id,
mode);
applet_resource->GetController<Controller_NPad>(HidController::NPad)
.SetNpadHandheldActivationMode(Controller_NPad::NpadHandheldActivationMode{mode});
LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
applet_resource_user_id, mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -753,13 +725,11 @@ void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 4};
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(
static_cast<u64>(applet_resource->GetController<Controller_NPad>(HidController::NPad)
.GetNpadHandheldActivationMode()));
}
void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
-2
View File
@@ -86,8 +86,6 @@ private:
void CreateAppletResource(Kernel::HLERequestContext& ctx);
void ActivateXpad(Kernel::HLERequestContext& ctx);
void GetXpadIDs(Kernel::HLERequestContext& ctx);
void ActivateSixAxisSensor(Kernel::HLERequestContext& ctx);
void DeactivateSixAxisSensor(Kernel::HLERequestContext& ctx);
void ActivateDebugPad(Kernel::HLERequestContext& ctx);
void ActivateTouchScreen(Kernel::HLERequestContext& ctx);
void ActivateMouse(Kernel::HLERequestContext& ctx);
+10 -13
View File
@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <array>
#include <atomic>
#include "common/logging/log.h"
@@ -73,10 +72,10 @@ private:
std::array<u8, 10> uuid;
u8 uuid_length; // TODO(ogniK): Figure out if this is actual the uuid length or does it
// mean something else
std::array<u8, 0x15> padding_1;
INSERT_PADDING_BYTES(0x15);
u32_le protocol;
u32_le tag_type;
std::array<u8, 0x2c> padding_2;
INSERT_PADDING_BYTES(0x2c);
};
static_assert(sizeof(TagInfo) == 0x54, "TagInfo is an invalid size");
@@ -214,15 +213,13 @@ private:
LOG_DEBUG(Service_NFP, "called");
IPC::ResponseBuilder rb{ctx, 2};
const auto& amiibo = nfp_interface.GetAmiiboBuffer();
const TagInfo tag_info{
.uuid = amiibo.uuid,
.uuid_length = static_cast<u8>(tag_info.uuid.size()),
.padding_1 = {},
.protocol = 1, // TODO(ogniK): Figure out actual values
.tag_type = 2,
.padding_2 = {},
};
auto amiibo = nfp_interface.GetAmiiboBuffer();
TagInfo tag_info{};
tag_info.uuid = amiibo.uuid;
tag_info.uuid_length = static_cast<u8>(tag_info.uuid.size());
tag_info.protocol = 1; // TODO(ogniK): Figure out actual values
tag_info.tag_type = 2;
ctx.WriteBuffer(tag_info);
rb.Push(RESULT_SUCCESS);
}
@@ -239,7 +236,7 @@ private:
LOG_DEBUG(Service_NFP, "called");
IPC::ResponseBuilder rb{ctx, 2};
const auto& amiibo = nfp_interface.GetAmiiboBuffer();
auto amiibo = nfp_interface.GetAmiiboBuffer();
ctx.WriteBuffer(amiibo.model_info);
rb.Push(RESULT_SUCCESS);
}
@@ -265,7 +265,7 @@ std::optional<nvhost_as_gpu::BufferMap> nvhost_as_gpu::FindBufferMap(GPUVAddr gp
}
}
return std::nullopt;
return {};
}
void nvhost_as_gpu::AddBufferMap(GPUVAddr gpu_addr, std::size_t size, VAddr cpu_addr,
@@ -286,7 +286,7 @@ std::optional<std::size_t> nvhost_as_gpu::RemoveBufferMap(GPUVAddr gpu_addr) {
return size;
}
return std::nullopt;
return {};
}
} // namespace Service::Nvidia::Devices
+1 -1
View File
@@ -54,7 +54,7 @@ struct EventInterface {
}
mask = mask >> 1;
}
return std::nullopt;
return {};
}
void SetEventStatus(const u32 event_id, EventState new_status) {
EventState old_status = status[event_id];
+3 -3
View File
@@ -114,7 +114,7 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
[&](const VI::Display& display) { return display.GetName() == name; });
if (itr == displays.end()) {
return std::nullopt;
return {};
}
return itr->GetID();
@@ -124,7 +124,7 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
auto* const display = FindDisplay(display_id);
if (display == nullptr) {
return std::nullopt;
return {};
}
const u64 layer_id = next_layer_id++;
@@ -144,7 +144,7 @@ std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) co
const auto* const layer = FindLayer(display_id, layer_id);
if (layer == nullptr) {
return std::nullopt;
return {};
}
return layer->GetBufferQueue().GetId();
+26 -2
View File
@@ -72,6 +72,25 @@
namespace Service {
/**
* Creates a function string for logging, complete with the name (or header code, depending
* on what's passed in) the port name, and all the cmd_buff arguments.
*/
[[maybe_unused]] static std::string MakeFunctionString(std::string_view name,
std::string_view port_name,
const u32* cmd_buff) {
// Number of params == bits 0-5 + bits 6-11
int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
std::string function_string = fmt::format("function '{}': port={}", name, port_name);
for (int i = 1; i <= num_params; ++i) {
function_string += fmt::format(", cmd_buff[{}]=0x{:X}", i, cmd_buff[i]);
}
return function_string;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_sessions,
InvokerFn* handler_invoker)
: service_name(service_name), max_sessions(max_sessions), handler_invoker(handler_invoker) {}
@@ -86,9 +105,10 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
port_installed = true;
}
void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) {
void ServiceFrameworkBase::InstallAsNamedPort() {
ASSERT(!port_installed);
auto& kernel = Core::System::GetInstance().Kernel();
auto [server_port, client_port] =
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
server_port->SetHleHandler(shared_from_this());
@@ -96,9 +116,10 @@ void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) {
port_installed = true;
}
std::shared_ptr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) {
std::shared_ptr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {
ASSERT(!port_installed);
auto& kernel = Core::System::GetInstance().Kernel();
auto [server_port, client_port] =
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
auto port = MakeResult(std::move(server_port)).Unwrap();
@@ -170,6 +191,9 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
return RESULT_SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Module interface
/// Initialize ServiceManager
void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {
// NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
+2 -2
View File
@@ -63,9 +63,9 @@ public:
/// Creates a port pair and registers this service with the given ServiceManager.
void InstallAsService(SM::ServiceManager& service_manager);
/// Creates a port pair and registers it on the kernel's global port registry.
void InstallAsNamedPort(Kernel::KernelCore& kernel);
void InstallAsNamedPort();
/// Creates and returns an unregistered port for the service.
std::shared_ptr<Kernel::ClientPort> CreatePort(Kernel::KernelCore& kernel);
std::shared_ptr<Kernel::ClientPort> CreatePort();
void InvokeRequest(Kernel::HLERequestContext& ctx);
+7 -6
View File
@@ -19,7 +19,7 @@ constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4);
constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6);
constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7);
ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {}
ServiceManager::ServiceManager() = default;
ServiceManager::~ServiceManager() = default;
void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
@@ -27,11 +27,11 @@ void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
}
static ResultCode ValidateServiceName(const std::string& name) {
if (name.empty() || name.size() > 8) {
if (name.size() <= 0 || name.size() > 8) {
LOG_ERROR(Service_SM, "Invalid service name! service={}", name);
return ERR_INVALID_NAME;
}
if (name.rfind('\0') != std::string::npos) {
if (name.find('\0') != std::string::npos) {
LOG_ERROR(Service_SM, "A non null terminated service was passed");
return ERR_INVALID_NAME;
}
@@ -43,13 +43,13 @@ void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self,
ASSERT(self->sm_interface.expired());
auto sm = std::make_shared<SM>(self, kernel);
sm->InstallAsNamedPort(kernel);
sm->InstallAsNamedPort();
self->sm_interface = sm;
self->controller_interface = std::make_unique<Controller>();
}
ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(std::string name,
u32 max_sessions) {
ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(
std::string name, unsigned int max_sessions) {
CASCADE_CODE(ValidateServiceName(name));
@@ -58,6 +58,7 @@ ResultVal<std::shared_ptr<Kernel::ServerPort>> ServiceManager::RegisterService(s
return ERR_ALREADY_REGISTERED;
}
auto& kernel = Core::System::GetInstance().Kernel();
auto [server_port, client_port] =
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, name);
+2 -5
View File
@@ -48,11 +48,11 @@ class ServiceManager {
public:
static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Kernel::KernelCore& kernel);
explicit ServiceManager(Kernel::KernelCore& kernel_);
ServiceManager();
~ServiceManager();
ResultVal<std::shared_ptr<Kernel::ServerPort>> RegisterService(std::string name,
u32 max_sessions);
unsigned int max_sessions);
ResultCode UnregisterService(const std::string& name);
ResultVal<std::shared_ptr<Kernel::ClientPort>> GetServicePort(const std::string& name);
ResultVal<std::shared_ptr<Kernel::ClientSession>> ConnectToService(const std::string& name);
@@ -79,9 +79,6 @@ private:
/// Map of registered services, retrieved using GetServicePort or ConnectToService.
std::unordered_map<std::string, std::shared_ptr<Kernel::ClientPort>> registered_services;
/// Kernel context
Kernel::KernelCore& kernel;
};
} // namespace Service::SM
@@ -29,7 +29,7 @@ namespace Service::Sockets {
* Worker abstraction to execute blocking calls on host without blocking the guest thread
*
* @tparam Service Service where the work is executed
* @tparam Types Types of work to execute
* @tparam ...Types Types of work to execute
*/
template <class Service, class... Types>
class BlockingWorker {
@@ -109,8 +109,9 @@ private:
while (keep_running) {
work_event.Wait();
const auto visit_fn = [service, &keep_running]<typename T>(T&& w) {
if constexpr (std::is_same_v<std::decay_t<T>, std::monostate>) {
const auto visit_fn = [service, &keep_running](auto&& w) {
using T = std::decay_t<decltype(w)>;
if constexpr (std::is_same_v<T, std::monostate>) {
keep_running = false;
} else {
w.Execute(service);
+4 -5
View File
@@ -491,13 +491,13 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::vector<u
for (PollFD& pollfd : fds) {
ASSERT(pollfd.revents == 0);
if (pollfd.fd > static_cast<s32>(MAX_FD) || pollfd.fd < 0) {
if (pollfd.fd > MAX_FD || pollfd.fd < 0) {
LOG_ERROR(Service, "File descriptor handle={} is invalid", pollfd.fd);
pollfd.revents = 0;
return {0, Errno::SUCCESS};
}
const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
if (!descriptor) {
LOG_ERROR(Service, "File descriptor handle={} is not allocated", pollfd.fd);
pollfd.revents = POLL_NVAL;
@@ -764,7 +764,6 @@ std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, const std::vector<u8>&
SockAddrIn guest_addr_in;
std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in));
addr_in = Translate(guest_addr_in);
p_addr_in = &addr_in;
}
return Translate(file_descriptors[fd]->socket->SendTo(flags, message, p_addr_in));
@@ -796,7 +795,7 @@ s32 BSD::FindFreeFileDescriptorHandle() noexcept {
}
bool BSD::IsFileDescriptorValid(s32 fd) const noexcept {
if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
if (fd > MAX_FD || fd < 0) {
LOG_ERROR(Service, "Invalid file descriptor handle={}", fd);
return false;
}
@@ -810,7 +809,7 @@ bool BSD::IsFileDescriptorValid(s32 fd) const noexcept {
bool BSD::IsBlockingSocket(s32 fd) const noexcept {
// Inform invalid sockets as non-blocking
// This way we avoid using a worker thread as it will fail without blocking host
if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
if (fd > MAX_FD || fd < 0) {
return false;
}
if (!file_descriptors[fd]) {
@@ -131,21 +131,21 @@ u16 TranslatePollEventsToGuest(u16 flags) {
Network::SockAddrIn Translate(SockAddrIn value) {
ASSERT(value.len == 0 || value.len == sizeof(value));
return {
.family = Translate(static_cast<Domain>(value.family)),
.ip = value.ip,
.portno = static_cast<u16>(value.portno >> 8 | value.portno << 8),
};
Network::SockAddrIn result;
result.family = Translate(static_cast<Domain>(value.family));
result.ip = value.ip;
result.portno = value.portno >> 8 | value.portno << 8;
return result;
}
SockAddrIn Translate(Network::SockAddrIn value) {
return {
.len = sizeof(SockAddrIn),
.family = static_cast<u8>(Translate(value.family)),
.portno = static_cast<u16>(value.portno >> 8 | value.portno << 8),
.ip = value.ip,
.zeroes = {},
};
SockAddrIn result;
result.len = sizeof(result);
result.family = static_cast<u8>(Translate(value.family));
result.portno = value.portno >> 8 | value.portno << 8;
result.ip = value.ip;
result.zeroes = {};
return result;
}
Network::ShutdownHow Translate(ShutdownHow how) {
@@ -89,7 +89,7 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::Virtua
}
AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load(
Kernel::Process& process, Core::System& system) {
Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
@@ -141,9 +141,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
continue;
}
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
process, system, *module_file, code_size, should_pass_arguments, false);
const bool should_pass_arguments{std::strcmp(module, "rtld") == 0};
const auto tentative_next_load_addr{AppLoader_NSO::LoadModule(
process, *module_file, code_size, should_pass_arguments, false)};
if (!tentative_next_load_addr) {
return {ResultStatus::ErrorLoadingNSO, {}};
}
@@ -168,9 +168,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
}
const VAddr load_addr{next_load_addr};
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
process, system, *module_file, load_addr, should_pass_arguments, true, pm);
const bool should_pass_arguments{std::strcmp(module, "rtld") == 0};
const auto tentative_next_load_addr{AppLoader_NSO::LoadModule(
process, *module_file, load_addr, should_pass_arguments, true, pm)};
if (!tentative_next_load_addr) {
return {ResultStatus::ErrorLoadingNSO, {}};
}
@@ -192,8 +192,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
// Register the RomFS if a ".romfs" file was found
if (romfs_iter != files.end() && *romfs_iter != nullptr) {
romfs = *romfs_iter;
system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
*this, system.GetContentProvider(), system.GetFileSystemController()));
Core::System::GetInstance().GetFileSystemController().RegisterRomFS(
std::make_unique<FileSys::RomFSFactory>(*this));
}
is_loaded = true;
@@ -9,10 +9,6 @@
#include "core/file_sys/program_metadata.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace Loader {
/**
@@ -41,7 +37,7 @@ public:
return IdentifyType(file);
}
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
+1 -2
View File
@@ -383,8 +383,7 @@ FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process,
[[maybe_unused]] Core::System& system) {
AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
+1 -5
View File
@@ -8,10 +8,6 @@
#include "common/common_types.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace Loader {
/// Loads an ELF/AXF file
@@ -30,7 +26,7 @@ public:
return IdentifyType(file);
}
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
};
} // namespace Loader
+1 -2
View File
@@ -43,8 +43,7 @@ FileType AppLoader_KIP::GetFileType() const {
: FileType::Error;
}
AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process,
[[maybe_unused]] Core::System& system) {
AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
+1 -5
View File
@@ -6,10 +6,6 @@
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace FileSys {
class KIP;
}
@@ -30,7 +26,7 @@ public:
FileType GetFileType() const override;
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
private:
std::unique_ptr<FileSys::KIP> kip;
+1 -6
View File
@@ -15,10 +15,6 @@
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/vfs.h"
namespace Core {
class System;
}
namespace FileSys {
class NACP;
} // namespace FileSys
@@ -158,10 +154,9 @@ public:
/**
* Load the application and return the created Process instance
* @param process The newly created process.
* @param system The system that this process is being loaded under.
* @return The status result of the operation.
*/
virtual LoadResult Load(Kernel::Process& process, Core::System& system) = 0;
virtual LoadResult Load(Kernel::Process& process) = 0;
/**
* Get the code (typically .code section) of the application
+2 -3
View File
@@ -41,8 +41,7 @@ FileType AppLoader_NAX::GetFileType() const {
return IdentifyTypeImpl(*nax);
}
AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process,
[[maybe_unused]] Core::System& system) {
AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
@@ -66,7 +65,7 @@ AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process,
return {nca_status, {}};
}
const auto result = nca_loader->Load(process, system);
const auto result = nca_loader->Load(process);
if (result.first != ResultStatus::Success) {
return result;
}
+3 -5
View File
@@ -8,12 +8,10 @@
#include "common/common_types.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace FileSys {
class NAX;
} // namespace FileSys
namespace Loader {
@@ -35,7 +33,7 @@ public:
FileType GetFileType() const override;
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
u64 ReadRomFSIVFCOffset() const override;
+4 -4
View File
@@ -31,7 +31,7 @@ FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process, Core::System& system) {
AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
@@ -52,14 +52,14 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process, Core::Sy
directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true);
const auto load_result = directory_loader->Load(process, system);
const auto load_result = directory_loader->Load(process);
if (load_result.first != ResultStatus::Success) {
return load_result;
}
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) {
system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
*this, system.GetContentProvider(), system.GetFileSystemController()));
Core::System::GetInstance().GetFileSystemController().RegisterRomFS(
std::make_unique<FileSys::RomFSFactory>(*this));
}
is_loaded = true;
+1 -5
View File
@@ -8,10 +8,6 @@
#include "core/file_sys/vfs.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace FileSys {
class NCA;
}
@@ -37,7 +33,7 @@ public:
return IdentifyType(file);
}
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
u64 ReadRomFSIVFCOffset() const override;
+3 -3
View File
@@ -208,7 +208,7 @@ bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& fi
return LoadNroImpl(process, file.ReadAllBytes(), file.GetName());
}
AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process, Core::System& system) {
AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
@@ -218,8 +218,8 @@ AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process, Core::Sy
}
if (romfs != nullptr) {
system.GetFileSystemController().RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(
*this, system.GetContentProvider(), system.GetFileSystemController()));
Core::System::GetInstance().GetFileSystemController().RegisterRomFS(
std::make_unique<FileSys::RomFSFactory>(*this));
}
is_loaded = true;
+1 -5
View File
@@ -10,10 +10,6 @@
#include "common/common_types.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace FileSys {
class NACP;
}
@@ -41,7 +37,7 @@ public:
return IdentifyType(file);
}
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
ResultStatus ReadProgramId(u64& out_program_id) override;
+7 -6
View File
@@ -71,21 +71,21 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::NSO;
}
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::System& system,
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
const FileSys::VfsFile& file, VAddr load_base,
bool should_pass_arguments, bool load_into_process,
std::optional<FileSys::PatchManager> pm) {
if (file.GetSize() < sizeof(NSOHeader)) {
return std::nullopt;
return {};
}
NSOHeader nso_header{};
if (sizeof(NSOHeader) != file.ReadObject(&nso_header)) {
return std::nullopt;
return {};
}
if (nso_header.magic != Common::MakeMagic('N', 'S', 'O', '0')) {
return std::nullopt;
return {};
}
// Build program image
@@ -148,6 +148,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S
// Apply cheats if they exist and the program has a valid title ID
if (pm) {
auto& system = Core::System::GetInstance();
system.SetCurrentProcessBuildID(nso_header.build_id);
const auto cheats = pm->CreateCheatList(system, nso_header.build_id);
if (!cheats.empty()) {
@@ -165,7 +166,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S
return load_base + image_size;
}
AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process, Core::System& system) {
AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
@@ -174,7 +175,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process, Core::Sy
// Load module
const VAddr base_address = process.PageTable().GetCodeRegionStart();
if (!LoadModule(process, system, *file, base_address, true, true)) {
if (!LoadModule(process, *file, base_address, true, true)) {
return {ResultStatus::ErrorLoadingNSO, {}};
}
+4 -8
View File
@@ -12,10 +12,6 @@
#include "core/file_sys/patch_manager.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace Kernel {
class Process;
}
@@ -84,12 +80,12 @@ public:
return IdentifyType(file);
}
static std::optional<VAddr> LoadModule(Kernel::Process& process, Core::System& system,
const FileSys::VfsFile& file, VAddr load_base,
bool should_pass_arguments, bool load_into_process,
static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file,
VAddr load_base, bool should_pass_arguments,
bool load_into_process,
std::optional<FileSys::PatchManager> pm = {});
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadNSOModules(Modules& modules) override;
+4 -3
View File
@@ -71,7 +71,7 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process, Core::System& system) {
AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
@@ -99,14 +99,15 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process, Core::Sy
return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
}
const auto result = secondary_loader->Load(process, system);
const auto result = secondary_loader->Load(process);
if (result.first != ResultStatus::Success) {
return result;
}
FileSys::VirtualFile update_raw;
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
system.GetFileSystemController().SetPackedUpdate(std::move(update_raw));
Core::System::GetInstance().GetFileSystemController().SetPackedUpdate(
std::move(update_raw));
}
is_loaded = true;
+1 -5
View File
@@ -9,10 +9,6 @@
#include "core/file_sys/vfs.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace FileSys {
class NACP;
class NSP;
@@ -39,7 +35,7 @@ public:
return IdentifyType(file);
}
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
u64 ReadRomFSIVFCOffset() const override;
+4 -3
View File
@@ -49,7 +49,7 @@ FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process, Core::System& system) {
AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
@@ -66,14 +66,15 @@ AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process, Core::Sy
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
}
const auto result = nca_loader->Load(process, system);
const auto result = nca_loader->Load(process);
if (result.first != ResultStatus::Success) {
return result;
}
FileSys::VirtualFile update_raw;
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
system.GetFileSystemController().SetPackedUpdate(std::move(update_raw));
Core::System::GetInstance().GetFileSystemController().SetPackedUpdate(
std::move(update_raw));
}
is_loaded = true;
+1 -5
View File
@@ -9,10 +9,6 @@
#include "core/file_sys/vfs.h"
#include "core/loader/loader.h"
namespace Core {
class System;
}
namespace FileSys {
class NACP;
class XCI;
@@ -39,7 +35,7 @@ public:
return IdentifyType(file);
}
LoadResult Load(Kernel::Process& process, Core::System& system) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
u64 ReadRomFSIVFCOffset() const override;
+22 -19
View File
@@ -19,24 +19,10 @@
#include "core/memory/cheat_engine.h"
namespace Core::Memory {
namespace {
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) {
auto end_index = start_index;
while (data[end_index] != match) {
++end_index;
if (end_index > data.size() ||
(end_index - start_index - 1) > sizeof(CheatDefinition::readable_name)) {
return {};
}
}
return data.substr(start_index, end_index - start_index);
}
} // Anonymous namespace
StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata)
: metadata(metadata), system(system) {}
@@ -96,9 +82,26 @@ CheatParser::~CheatParser() = default;
TextCheatParser::~TextCheatParser() = default;
std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
namespace {
template <char match>
std::string_view ExtractName(std::string_view data, std::size_t start_index) {
auto end_index = start_index;
while (data[end_index] != match) {
++end_index;
if (end_index > data.size() ||
(end_index - start_index - 1) > sizeof(CheatDefinition::readable_name)) {
return {};
}
}
return data.substr(start_index, end_index - start_index);
}
} // Anonymous namespace
std::vector<CheatEntry> TextCheatParser::Parse(const Core::System& system,
std::string_view data) const {
std::vector<CheatEntry> out(1);
std::optional<u64> current_entry;
std::optional<u64> current_entry = std::nullopt;
for (std::size_t i = 0; i < data.size(); ++i) {
if (::isspace(data[i])) {
@@ -112,7 +115,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
return {};
}
const auto name = ExtractName(data, i + 1, '}');
const auto name = ExtractName<'}'>(data, i + 1);
if (name.empty()) {
return {};
}
@@ -129,7 +132,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
current_entry = out.size();
out.emplace_back();
const auto name = ExtractName(data, i + 1, ']');
const auto name = ExtractName<']'>(data, i + 1);
if (name.empty()) {
return {};
}
+3 -2
View File
@@ -47,7 +47,8 @@ class CheatParser {
public:
virtual ~CheatParser();
[[nodiscard]] virtual std::vector<CheatEntry> Parse(std::string_view data) const = 0;
virtual std::vector<CheatEntry> Parse(const Core::System& system,
std::string_view data) const = 0;
};
// CheatParser implementation that parses text files
@@ -55,7 +56,7 @@ class TextCheatParser final : public CheatParser {
public:
~TextCheatParser() override;
[[nodiscard]] std::vector<CheatEntry> Parse(std::string_view data) const override;
std::vector<CheatEntry> Parse(const Core::System& system, std::string_view data) const override;
};
// Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming
-1
View File
@@ -152,7 +152,6 @@ struct Values {
bool vibration_enabled;
bool motion_enabled;
std::string motion_device;
std::string touch_device;
TouchscreenInput touchscreen;
@@ -4,16 +4,7 @@
#include <chrono>
#include <thread>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
#endif
#include <libusb.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "common/logging/log.h"
#include "input_common/gcadapter/gc_adapter.h"
+3 -43
View File
@@ -12,7 +12,6 @@
#include "input_common/main.h"
#include "input_common/motion_emu.h"
#include "input_common/touch_from_button.h"
#include "input_common/udp/client.h"
#include "input_common/udp/udp.h"
#ifdef HAVE_SDL2
#include "input_common/sdl/sdl.h"
@@ -41,11 +40,7 @@ struct InputSubsystem::Impl {
sdl = SDL::Init();
#endif
udp = std::make_shared<InputCommon::CemuhookUDP::Client>();
udpmotion = std::make_shared<UDPMotionFactory>(udp);
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", udpmotion);
udptouch = std::make_shared<UDPTouchFactory>(udp);
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", udptouch);
udp = CemuhookUDP::Init();
}
void Shutdown() {
@@ -58,17 +53,12 @@ struct InputSubsystem::Impl {
#ifdef HAVE_SDL2
sdl.reset();
#endif
udp.reset();
Input::UnregisterFactory<Input::ButtonDevice>("gcpad");
Input::UnregisterFactory<Input::AnalogDevice>("gcpad");
gcbuttons.reset();
gcanalog.reset();
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
udpmotion.reset();
udptouch.reset();
}
[[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {
@@ -119,28 +109,14 @@ struct InputSubsystem::Impl {
return {};
}
[[nodiscard]] MotionMapping GetMotionMappingForDevice(
const Common::ParamPackage& params) const {
if (!params.Has("class") || params.Get("class", "") == "any") {
return {};
}
if (params.Get("class", "") == "cemuhookudp") {
// TODO return the correct motion device
return {};
}
return {};
}
std::shared_ptr<Keyboard> keyboard;
std::shared_ptr<MotionEmu> motion_emu;
#ifdef HAVE_SDL2
std::unique_ptr<SDL::State> sdl;
#endif
std::unique_ptr<CemuhookUDP::State> udp;
std::shared_ptr<GCButtonFactory> gcbuttons;
std::shared_ptr<GCAnalogFactory> gcanalog;
std::shared_ptr<UDPMotionFactory> udpmotion;
std::shared_ptr<UDPTouchFactory> udptouch;
std::shared_ptr<CemuhookUDP::Client> udp;
};
InputSubsystem::InputSubsystem() : impl{std::make_unique<Impl>()} {}
@@ -199,22 +175,6 @@ const GCButtonFactory* InputSubsystem::GetGCButtons() const {
return impl->gcbuttons.get();
}
UDPMotionFactory* InputSubsystem::GetUDPMotions() {
return impl->udpmotion.get();
}
const UDPMotionFactory* InputSubsystem::GetUDPMotions() const {
return impl->udpmotion.get();
}
UDPTouchFactory* InputSubsystem::GetUDPTouch() {
return impl->udptouch.get();
}
const UDPTouchFactory* InputSubsystem::GetUDPTouch() const {
return impl->udptouch.get();
}
void InputSubsystem::ReloadInputDevices() {
if (!impl->udp) {
return;
+1 -23
View File
@@ -21,14 +21,10 @@ namespace Settings::NativeButton {
enum Values : int;
}
namespace Settings::NativeMotion {
enum Values : int;
}
namespace InputCommon {
namespace Polling {
enum class DeviceType { Button, AnalogPreferred, Motion };
enum class DeviceType { Button, AnalogPreferred };
/**
* A class that can be used to get inputs from an input device like controllers without having to
@@ -54,8 +50,6 @@ public:
class GCAnalogFactory;
class GCButtonFactory;
class UDPMotionFactory;
class UDPTouchFactory;
class Keyboard;
class MotionEmu;
@@ -65,7 +59,6 @@ class MotionEmu;
*/
using AnalogMapping = std::unordered_map<Settings::NativeAnalog::Values, Common::ParamPackage>;
using ButtonMapping = std::unordered_map<Settings::NativeButton::Values, Common::ParamPackage>;
using MotionMapping = std::unordered_map<Settings::NativeMotion::Values, Common::ParamPackage>;
class InputSubsystem {
public:
@@ -110,9 +103,6 @@ public:
/// Retrieves the button mappings for the given device.
[[nodiscard]] ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& device) const;
/// Retrieves the motion mappings for the given device.
[[nodiscard]] MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& device) const;
/// Retrieves the underlying GameCube analog handler.
[[nodiscard]] GCAnalogFactory* GetGCAnalogs();
@@ -125,18 +115,6 @@ public:
/// Retrieves the underlying GameCube button handler.
[[nodiscard]] const GCButtonFactory* GetGCButtons() const;
/// Retrieves the underlying udp motion handler.
[[nodiscard]] UDPMotionFactory* GetUDPMotions();
/// Retrieves the underlying udp motion handler.
[[nodiscard]] const UDPMotionFactory* GetUDPMotions() const;
/// Retrieves the underlying udp touch handler.
[[nodiscard]] UDPTouchFactory* GetUDPTouch();
/// Retrieves the underlying udp touch handler.
[[nodiscard]] const UDPTouchFactory* GetUDPTouch() const;
/// Reloads the input devices
void ReloadInputDevices();
+4 -13
View File
@@ -56,7 +56,7 @@ public:
is_tilting = false;
}
Input::MotionStatus GetStatus() {
std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() {
std::lock_guard guard{status_mutex};
return status;
}
@@ -76,7 +76,7 @@ private:
Common::Event shutdown_event;
Input::MotionStatus status;
std::tuple<Common::Vec3<float>, Common::Vec3<float>> status;
std::mutex status_mutex;
// Note: always keep the thread declaration at the end so that other objects are initialized
@@ -113,19 +113,10 @@ private:
gravity = QuaternionRotate(inv_q, gravity);
angular_rate = QuaternionRotate(inv_q, angular_rate);
// TODO: Calculate the correct rotation vector and orientation matrix
const auto matrix4x4 = q.ToMatrix();
const auto rotation = Common::MakeVec(0.0f, 0.0f, 0.0f);
const std::array orientation{
Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10]),
};
// Update the sensor state
{
std::lock_guard guard{status_mutex};
status = std::make_tuple(gravity, angular_rate, rotation, orientation);
status = std::make_tuple(gravity, angular_rate);
}
}
}
@@ -140,7 +131,7 @@ public:
device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity);
}
Input::MotionStatus GetStatus() const override {
std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override {
return device->GetStatus();
}
-7
View File
@@ -14,13 +14,6 @@ const std::array<const char*, NumButtons> mapping = {{
}};
}
namespace NativeMotion {
const std::array<const char*, NumMotions> mapping = {{
"motionleft",
"motionright",
}};
}
namespace NativeAnalog {
const std::array<const char*, NumAnalogs> mapping = {{
"lstick",
-17
View File
@@ -66,21 +66,6 @@ constexpr int NUM_STICKS_HID = NumAnalogs;
extern const std::array<const char*, NumAnalogs> mapping;
} // namespace NativeAnalog
namespace NativeMotion {
enum Values : int {
MOTIONLEFT,
MOTIONRIGHT,
NumMotions,
};
constexpr int MOTION_HID_BEGIN = MOTIONLEFT;
constexpr int MOTION_HID_END = NumMotions;
constexpr int NUM_MOTION_HID = NumMotions;
extern const std::array<const char*, NumMotions> mapping;
} // namespace NativeMotion
namespace NativeMouseButton {
enum Values {
Left,
@@ -307,7 +292,6 @@ constexpr int NUM_KEYBOARD_MODS_HID = NumKeyboardMods;
using ButtonsRaw = std::array<std::string, NativeButton::NumButtons>;
using AnalogsRaw = std::array<std::string, NativeAnalog::NumAnalogs>;
using MotionRaw = std::array<std::string, NativeMotion::NumMotions>;
using MouseButtonsRaw = std::array<std::string, NativeMouseButton::NumMouseButtons>;
using KeyboardKeysRaw = std::array<std::string, NativeKeyboard::NumKeyboardKeys>;
using KeyboardModsRaw = std::array<std::string, NativeKeyboard::NumKeyboardMods>;
@@ -330,7 +314,6 @@ struct PlayerInput {
ControllerType controller_type;
ButtonsRaw buttons;
AnalogsRaw analogs;
MotionRaw motions;
std::string lstick_mod;
std::string rstick_mod;
+30 -146
View File
@@ -2,13 +2,14 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <array>
#include <chrono>
#include <cstring>
#include <functional>
#include <thread>
#include <boost/asio.hpp>
#include "common/logging/log.h"
#include "core/settings.h"
#include "input_common/udp/client.h"
#include "input_common/udp/protocol.h"
@@ -130,59 +131,21 @@ static void SocketLoop(Socket* socket) {
socket->Loop();
}
Client::Client() {
LOG_INFO(Input, "Udp Initialization started");
for (std::size_t client = 0; client < clients.size(); client++) {
u8 pad = client % 4;
StartCommunication(client, Settings::values.udp_input_address,
Settings::values.udp_input_port, pad, 24872);
// Set motion parameters
// SetGyroThreshold value should be dependent on GyroscopeZeroDriftMode
// Real HW values are unknown, 0.0001 is an approximate to Standard
clients[client].motion.SetGyroThreshold(0.0001f);
}
Client::Client(std::shared_ptr<DeviceStatus> status, const std::string& host, u16 port,
u8 pad_index, u32 client_id)
: status(std::move(status)) {
StartCommunication(host, port, pad_index, client_id);
}
Client::~Client() {
Reset();
socket->Stop();
thread.join();
}
std::vector<Common::ParamPackage> Client::GetInputDevices() const {
std::vector<Common::ParamPackage> devices;
for (std::size_t client = 0; client < clients.size(); client++) {
if (!DeviceConnected(client)) {
continue;
}
std::string name = fmt::format("UDP Controller {}", client);
devices.emplace_back(Common::ParamPackage{
{"class", "cemuhookudp"},
{"display", std::move(name)},
{"port", std::to_string(client)},
});
}
return devices;
}
bool Client::DeviceConnected(std::size_t pad) const {
// Use last timestamp to detect if the socket has stopped sending data
const auto now = std::chrono::system_clock::now();
u64 time_difference =
std::chrono::duration_cast<std::chrono::milliseconds>(now - clients[pad].last_motion_update)
.count();
return time_difference < 1000 && clients[pad].active == 1;
}
void Client::ReloadUDPClient() {
for (std::size_t client = 0; client < clients.size(); client++) {
ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port, client);
}
}
void Client::ReloadSocket(const std::string& host, u16 port, u8 pad_index, u32 client_id) {
// client number must be determined from host / port and pad index
std::size_t client = pad_index;
clients[client].socket->Stop();
clients[client].thread.join();
StartCommunication(client, host, port, pad_index, client_id);
socket->Stop();
thread.join();
StartCommunication(host, port, pad_index, client_id);
}
void Client::OnVersion(Response::Version data) {
@@ -194,39 +157,23 @@ void Client::OnPortInfo(Response::PortInfo data) {
}
void Client::OnPadData(Response::PadData data) {
// client number must be determined from host / port and pad index
std::size_t client = data.info.id;
LOG_TRACE(Input, "PadData packet received");
if (data.packet_counter == clients[client].packet_sequence) {
if (data.packet_counter <= packet_sequence) {
LOG_WARNING(
Input,
"PadData packet dropped because its stale info. Current count: {} Packet count: {}",
clients[client].packet_sequence, data.packet_counter);
packet_sequence, data.packet_counter);
return;
}
clients[client].active = data.info.is_pad_active;
clients[client].packet_sequence = data.packet_counter;
const auto now = std::chrono::system_clock::now();
u64 time_difference = std::chrono::duration_cast<std::chrono::microseconds>(
now - clients[client].last_motion_update)
.count();
clients[client].last_motion_update = now;
Common::Vec3f raw_gyroscope = {data.gyro.pitch, data.gyro.roll, -data.gyro.yaw};
clients[client].motion.SetAcceleration({data.accel.x, -data.accel.z, data.accel.y});
// Gyroscope values are not it the correct scale from better joy.
// Dividing by 312 allows us to make one full turn = 1 turn
// This must be a configurable valued called sensitivity
clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f);
clients[client].motion.UpdateRotation(time_difference);
clients[client].motion.UpdateOrientation(time_difference);
Common::Vec3f gyroscope = clients[client].motion.GetGyroscope();
Common::Vec3f accelerometer = clients[client].motion.GetAcceleration();
Common::Vec3f rotation = clients[client].motion.GetRotations();
std::array<Common::Vec3f, 3> orientation = clients[client].motion.GetOrientation();
packet_sequence = data.packet_counter;
// TODO: Check how the Switch handles motions and how the CemuhookUDP motion
// directions correspond to the ones of the Switch
Common::Vec3f accel = Common::MakeVec<float>(data.accel.x, data.accel.y, data.accel.z);
Common::Vec3f gyro = Common::MakeVec<float>(data.gyro.pitch, data.gyro.yaw, data.gyro.roll);
{
std::lock_guard guard(clients[client].status.update_mutex);
clients[client].status.motion_status = {accelerometer, gyroscope, rotation, orientation};
std::lock_guard guard(status->update_mutex);
status->motion_status = {accel, gyro};
// TODO: add a setting for "click" touch. Click touch refers to a device that differentiates
// between a simple "tap" and a hard press that causes the touch screen to click.
@@ -235,11 +182,11 @@ void Client::OnPadData(Response::PadData data) {
float x = 0;
float y = 0;
if (is_active && clients[client].status.touch_calibration) {
const u16 min_x = clients[client].status.touch_calibration->min_x;
const u16 max_x = clients[client].status.touch_calibration->max_x;
const u16 min_y = clients[client].status.touch_calibration->min_y;
const u16 max_y = clients[client].status.touch_calibration->max_y;
if (is_active && status->touch_calibration) {
const u16 min_x = status->touch_calibration->min_x;
const u16 max_x = status->touch_calibration->max_x;
const u16 min_y = status->touch_calibration->min_y;
const u16 max_y = status->touch_calibration->max_y;
x = (std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - min_x) /
static_cast<float>(max_x - min_x);
@@ -247,80 +194,17 @@ void Client::OnPadData(Response::PadData data) {
static_cast<float>(max_y - min_y);
}
clients[client].status.touch_status = {x, y, is_active};
if (configuring) {
UpdateYuzuSettings(client, accelerometer, gyroscope, is_active);
}
status->touch_status = {x, y, is_active};
}
}
void Client::StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index,
u32 client_id) {
void Client::StartCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id) {
SocketCallback callback{[this](Response::Version version) { OnVersion(version); },
[this](Response::PortInfo info) { OnPortInfo(info); },
[this](Response::PadData data) { OnPadData(data); }};
LOG_INFO(Input, "Starting communication with UDP input server on {}:{}", host, port);
clients[client].socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
clients[client].thread = std::thread{SocketLoop, clients[client].socket.get()};
}
void Client::Reset() {
for (std::size_t client = 0; client < clients.size(); client++) {
clients[client].socket->Stop();
clients[client].thread.join();
}
}
void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
const Common::Vec3<float>& gyro, bool touch) {
UDPPadStatus pad;
if (touch) {
pad.touch = PadTouch::Click;
pad_queue[client].Push(pad);
}
for (size_t i = 0; i < 3; ++i) {
if (gyro[i] > 6.0f || gyro[i] < -6.0f) {
pad.motion = static_cast<PadMotion>(i);
pad.motion_value = gyro[i];
pad_queue[client].Push(pad);
}
if (acc[i] > 2.0f || acc[i] < -2.0f) {
pad.motion = static_cast<PadMotion>(i + 3);
pad.motion_value = acc[i];
pad_queue[client].Push(pad);
}
}
}
void Client::BeginConfiguration() {
for (auto& pq : pad_queue) {
pq.Clear();
}
configuring = true;
}
void Client::EndConfiguration() {
for (auto& pq : pad_queue) {
pq.Clear();
}
configuring = false;
}
DeviceStatus& Client::GetPadState(std::size_t pad) {
return clients[pad].status;
}
const DeviceStatus& Client::GetPadState(std::size_t pad) const {
return clients[pad].status;
}
std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() {
return pad_queue;
}
const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& Client::GetPadQueue() const {
return pad_queue;
socket = std::make_unique<Socket>(host, port, pad_index, client_id, callback);
thread = std::thread{SocketLoop, this->socket.get()};
}
void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id,
+8 -69
View File
@@ -12,12 +12,8 @@
#include <thread>
#include <tuple>
#include "common/common_types.h"
#include "common/param_package.h"
#include "common/thread.h"
#include "common/threadsafe_queue.h"
#include "common/vector_math.h"
#include "core/frontend/input.h"
#include "input_common/motion_input.h"
namespace InputCommon::CemuhookUDP {
@@ -32,30 +28,9 @@ struct PortInfo;
struct Version;
} // namespace Response
enum class PadMotion {
GyroX,
GyroY,
GyroZ,
AccX,
AccY,
AccZ,
Undefined,
};
enum class PadTouch {
Click,
Undefined,
};
struct UDPPadStatus {
PadTouch touch{PadTouch::Undefined};
PadMotion motion{PadMotion::Undefined};
f32 motion_value{0.0f};
};
struct DeviceStatus {
std::mutex update_mutex;
Input::MotionStatus motion_status;
std::tuple<Common::Vec3<float>, Common::Vec3<float>> motion_status;
std::tuple<float, float, bool> touch_status;
// calibration data for scaling the device's touch area to 3ds
@@ -70,58 +45,22 @@ struct DeviceStatus {
class Client {
public:
// Initialize the UDP client capture and read sequence
Client();
// Close and release the client
explicit Client(std::shared_ptr<DeviceStatus> status, const std::string& host = DEFAULT_ADDR,
u16 port = DEFAULT_PORT, u8 pad_index = 0, u32 client_id = 24872);
~Client();
// Used for polling
void BeginConfiguration();
void EndConfiguration();
std::vector<Common::ParamPackage> GetInputDevices() const;
bool DeviceConnected(std::size_t pad) const;
void ReloadUDPClient();
void ReloadSocket(const std::string& host = "127.0.0.1", u16 port = 26760, u8 pad_index = 0,
u32 client_id = 24872);
std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue();
const std::array<Common::SPSCQueue<UDPPadStatus>, 4>& GetPadQueue() const;
DeviceStatus& GetPadState(std::size_t pad);
const DeviceStatus& GetPadState(std::size_t pad) const;
private:
struct ClientData {
std::unique_ptr<Socket> socket;
DeviceStatus status;
std::thread thread;
u64 packet_sequence = 0;
u8 active;
// Realtime values
// motion is initalized with PID values for drift correction on joycons
InputCommon::MotionInput motion{0.3f, 0.005f, 0.0f};
std::chrono::time_point<std::chrono::system_clock> last_motion_update;
};
// For shutting down, clear all data, join all threads, release usb
void Reset();
void OnVersion(Response::Version);
void OnPortInfo(Response::PortInfo);
void OnPadData(Response::PadData);
void StartCommunication(std::size_t client, const std::string& host, u16 port, u8 pad_index,
u32 client_id);
void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
const Common::Vec3<float>& gyro, bool touch);
void StartCommunication(const std::string& host, u16 port, u8 pad_index, u32 client_id);
bool configuring = false;
std::array<ClientData, 4> clients;
std::array<Common::SPSCQueue<UDPPadStatus>, 4> pad_queue;
std::unique_ptr<Socket> socket;
std::shared_ptr<DeviceStatus> status;
std::thread thread;
u64 packet_sequence = 0;
};
/// An async job allowing configuration of the touchpad calibration.
+87 -126
View File
@@ -1,144 +1,105 @@
// Copyright 2020 yuzu Emulator Project
// Copyright 2018 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <atomic>
#include <list>
#include <mutex>
#include <utility>
#include "common/assert.h"
#include "common/threadsafe_queue.h"
#include <optional>
#include <tuple>
#include "common/param_package.h"
#include "core/frontend/input.h"
#include "core/settings.h"
#include "input_common/udp/client.h"
#include "input_common/udp/udp.h"
namespace InputCommon {
namespace InputCommon::CemuhookUDP {
class UDPMotion final : public Input::MotionDevice {
class UDPTouchDevice final : public Input::TouchDevice {
public:
UDPMotion(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_)
: ip(ip_), port(port_), pad(pad_), client(client_) {}
Input::MotionStatus GetStatus() const override {
return client->GetPadState(pad).motion_status;
}
private:
const std::string ip;
const int port;
const int pad;
CemuhookUDP::Client* client;
mutable std::mutex mutex;
};
/// A motion device factory that creates motion devices from JC Adapter
UDPMotionFactory::UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_)
: client(std::move(client_)) {}
/**
* Creates motion device
* @param params contains parameters for creating the device:
* - "port": the nth jcpad on the adapter
*/
std::unique_ptr<Input::MotionDevice> UDPMotionFactory::Create(const Common::ParamPackage& params) {
const std::string ip = params.Get("ip", "127.0.0.1");
const int port = params.Get("port", 26760);
const int pad = params.Get("pad_index", 0);
return std::make_unique<UDPMotion>(ip, port, pad, client.get());
}
void UDPMotionFactory::BeginConfiguration() {
polling = true;
client->BeginConfiguration();
}
void UDPMotionFactory::EndConfiguration() {
polling = false;
client->EndConfiguration();
}
Common::ParamPackage UDPMotionFactory::GetNextInput() {
Common::ParamPackage params;
CemuhookUDP::UDPPadStatus pad;
auto& queue = client->GetPadQueue();
for (std::size_t pad_number = 0; pad_number < queue.size(); ++pad_number) {
while (queue[pad_number].Pop(pad)) {
if (pad.motion == CemuhookUDP::PadMotion::Undefined || std::abs(pad.motion_value) < 1) {
continue;
}
params.Set("engine", "cemuhookudp");
params.Set("ip", "127.0.0.1");
params.Set("port", 26760);
params.Set("pad_index", static_cast<int>(pad_number));
params.Set("motion", static_cast<u16>(pad.motion));
return params;
}
}
return params;
}
class UDPTouch final : public Input::TouchDevice {
public:
UDPTouch(std::string ip_, int port_, int pad_, CemuhookUDP::Client* client_)
: ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {}
explicit UDPTouchDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
std::tuple<float, float, bool> GetStatus() const override {
return client->GetPadState(pad).touch_status;
std::lock_guard guard(status->update_mutex);
return status->touch_status;
}
private:
const std::string ip;
const int port;
const int pad;
CemuhookUDP::Client* client;
mutable std::mutex mutex;
std::shared_ptr<DeviceStatus> status;
};
/// A motion device factory that creates motion devices from JC Adapter
UDPTouchFactory::UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_)
: client(std::move(client_)) {}
/**
* Creates motion device
* @param params contains parameters for creating the device:
* - "port": the nth jcpad on the adapter
*/
std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamPackage& params) {
const std::string ip = params.Get("ip", "127.0.0.1");
const int port = params.Get("port", 26760);
const int pad = params.Get("pad_index", 0);
return std::make_unique<UDPTouch>(ip, port, pad, client.get());
}
void UDPTouchFactory::BeginConfiguration() {
polling = true;
client->BeginConfiguration();
}
void UDPTouchFactory::EndConfiguration() {
polling = false;
client->EndConfiguration();
}
Common::ParamPackage UDPTouchFactory::GetNextInput() {
Common::ParamPackage params;
CemuhookUDP::UDPPadStatus pad;
auto& queue = client->GetPadQueue();
for (std::size_t pad_number = 0; pad_number < queue.size(); ++pad_number) {
while (queue[pad_number].Pop(pad)) {
if (pad.touch == CemuhookUDP::PadTouch::Undefined) {
continue;
}
params.Set("engine", "cemuhookudp");
params.Set("ip", "127.0.0.1");
params.Set("port", 26760);
params.Set("pad_index", static_cast<int>(pad_number));
params.Set("touch", static_cast<u16>(pad.touch));
return params;
}
class UDPMotionDevice final : public Input::MotionDevice {
public:
explicit UDPMotionDevice(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override {
std::lock_guard guard(status->update_mutex);
return status->motion_status;
}
return params;
private:
std::shared_ptr<DeviceStatus> status;
};
class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> {
public:
explicit UDPTouchFactory(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override {
{
std::lock_guard guard(status->update_mutex);
status->touch_calibration = DeviceStatus::CalibrationData{};
// These default values work well for DS4 but probably not other touch inputs
status->touch_calibration->min_x = params.Get("min_x", 100);
status->touch_calibration->min_y = params.Get("min_y", 50);
status->touch_calibration->max_x = params.Get("max_x", 1800);
status->touch_calibration->max_y = params.Get("max_y", 850);
}
return std::make_unique<UDPTouchDevice>(status);
}
private:
std::shared_ptr<DeviceStatus> status;
};
class UDPMotionFactory final : public Input::Factory<Input::MotionDevice> {
public:
explicit UDPMotionFactory(std::shared_ptr<DeviceStatus> status_) : status(std::move(status_)) {}
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override {
return std::make_unique<UDPMotionDevice>(status);
}
private:
std::shared_ptr<DeviceStatus> status;
};
State::State() {
auto status = std::make_shared<DeviceStatus>();
client =
std::make_unique<Client>(status, Settings::values.udp_input_address,
Settings::values.udp_input_port, Settings::values.udp_pad_index);
motion_factory = std::make_shared<UDPMotionFactory>(status);
touch_factory = std::make_shared<UDPTouchFactory>(status);
Input::RegisterFactory<Input::MotionDevice>("cemuhookudp", motion_factory);
Input::RegisterFactory<Input::TouchDevice>("cemuhookudp", touch_factory);
}
} // namespace InputCommon
State::~State() {
Input::UnregisterFactory<Input::TouchDevice>("cemuhookudp");
Input::UnregisterFactory<Input::MotionDevice>("cemuhookudp");
}
std::vector<Common::ParamPackage> State::GetInputDevices() const {
// TODO support binding udp devices
return {};
}
void State::ReloadUDPClient() {
client->ReloadSocket(Settings::values.udp_input_address, Settings::values.udp_input_port,
Settings::values.udp_pad_index);
}
std::unique_ptr<State> Init() {
return std::make_unique<State>();
}
} // namespace InputCommon::CemuhookUDP
+18 -43
View File
@@ -1,57 +1,32 @@
// Copyright 2020 yuzu Emulator Project
// Copyright 2018 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include "core/frontend/input.h"
#include "input_common/udp/client.h"
#include <vector>
#include "common/param_package.h"
namespace InputCommon {
namespace InputCommon::CemuhookUDP {
/// A motion device factory that creates motion devices from udp clients
class UDPMotionFactory final : public Input::Factory<Input::MotionDevice> {
class Client;
class UDPMotionFactory;
class UDPTouchFactory;
class State {
public:
explicit UDPMotionFactory(std::shared_ptr<CemuhookUDP::Client> client_);
std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
Common::ParamPackage GetNextInput();
/// For device input configuration/polling
void BeginConfiguration();
void EndConfiguration();
bool IsPolling() const {
return polling;
}
State();
~State();
void ReloadUDPClient();
std::vector<Common::ParamPackage> GetInputDevices() const;
private:
std::shared_ptr<CemuhookUDP::Client> client;
bool polling = false;
std::unique_ptr<Client> client;
std::shared_ptr<UDPMotionFactory> motion_factory;
std::shared_ptr<UDPTouchFactory> touch_factory;
};
/// A touch device factory that creates touch devices from udp clients
class UDPTouchFactory final : public Input::Factory<Input::TouchDevice> {
public:
explicit UDPTouchFactory(std::shared_ptr<CemuhookUDP::Client> client_);
std::unique_ptr<State> Init();
std::unique_ptr<Input::TouchDevice> Create(const Common::ParamPackage& params) override;
Common::ParamPackage GetNextInput();
/// For device input configuration/polling
void BeginConfiguration();
void EndConfiguration();
bool IsPolling() const {
return polling;
}
private:
std::shared_ptr<CemuhookUDP::Client> client;
bool polling = false;
};
} // namespace InputCommon
} // namespace InputCommon::CemuhookUDP
+1 -1
View File
@@ -269,5 +269,5 @@ endif()
if (MSVC)
target_compile_options(video_core PRIVATE /we4267)
else()
target_compile_options(video_core PRIVATE -Werror=conversion -Wno-error=sign-conversion -Werror=switch)
target_compile_options(video_core PRIVATE -Werror=conversion -Wno-error=sign-conversion)
endif()
+6 -6
View File
@@ -87,12 +87,12 @@ void Fermi2D::HandleSurfaceCopy() {
const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2};
const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, dst_blit_x2,
dst_blit_y2};
const Config copy_config{
.operation = regs.operation,
.filter = regs.blit_control.filter,
.src_rect = src_rect,
.dst_rect = dst_rect,
};
Config copy_config;
copy_config.operation = regs.operation;
copy_config.filter = regs.blit_control.filter;
copy_config.src_rect = src_rect;
copy_config.dst_rect = dst_rect;
if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, copy_config)) {
UNIMPLEMENTED();
}
+2 -2
View File
@@ -145,8 +145,8 @@ public:
} regs{};
struct Config {
Operation operation{};
Filter filter{};
Operation operation;
Filter filter;
Common::Rectangle<u32> src_rect;
Common::Rectangle<u32> dst_rect;
};
+1 -1
View File
@@ -597,7 +597,7 @@ std::optional<u64> Maxwell3D::GetQueryResult() {
// Deferred.
rasterizer->Query(regs.query.QueryAddress(), VideoCore::QueryType::SamplesPassed,
system.GPU().GetTicks());
return std::nullopt;
return {};
default:
LOG_DEBUG(HW_GPU, "Unimplemented query select type {}",
static_cast<u32>(regs.query.query_get.select.Value()));
+1 -1
View File
@@ -36,7 +36,7 @@ void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method,
}
} else {
// Macro not compiled, check if it's uploaded and if so, compile it
std::optional<u32> mid_method;
std::optional<u32> mid_method = std::nullopt;
const auto macro_code = uploaded_macro_code.find(method);
if (macro_code == uploaded_macro_code.end()) {
for (const auto& [method_base, code] : uploaded_macro_code) {
+3 -3
View File
@@ -58,7 +58,7 @@ void MemoryManager::Unmap(GPUVAddr gpu_addr, std::size_t size) {
std::optional<GPUVAddr> MemoryManager::AllocateFixed(GPUVAddr gpu_addr, std::size_t size) {
for (u64 offset{}; offset < size; offset += page_size) {
if (!GetPageEntry(gpu_addr + offset).IsUnmapped()) {
return std::nullopt;
return {};
}
}
@@ -135,13 +135,13 @@ std::optional<GPUVAddr> MemoryManager::FindFreeRange(std::size_t size, std::size
}
}
return std::nullopt;
return {};
}
std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const {
const auto page_entry{GetPageEntry(gpu_addr)};
if (!page_entry.IsValid()) {
return std::nullopt;
return {};
}
return page_entry.ToAddress() + (gpu_addr & page_mask);
+5
View File
@@ -46,6 +46,11 @@ public:
/// Finalize rendering the guest frame and draw into the presentation texture
virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0;
/// Draws the latest frame to the window waiting timeout_ms for a frame to arrive (Renderer
/// specific implementation)
/// Returns true if a frame was drawn
virtual bool TryPresent(int timeout_ms) = 0;
// Getter/setter functions:
// ------------------------
@@ -813,7 +813,7 @@ private:
const u8 location = static_cast<u8>(static_cast<u32>(index) * 4 + element);
const auto it = transform_feedback.find(location);
if (it == transform_feedback.end()) {
return std::nullopt;
return {};
}
return it->second.components;
}
@@ -1295,21 +1295,21 @@ private:
switch (element) {
case 0:
UNIMPLEMENTED();
return std::nullopt;
return {};
case 1:
if (stage == ShaderType::Vertex && !device.HasVertexViewportLayer()) {
return std::nullopt;
return {};
}
return {{"gl_Layer", Type::Int}};
case 2:
if (stage == ShaderType::Vertex && !device.HasVertexViewportLayer()) {
return std::nullopt;
return {};
}
return {{"gl_ViewportIndex", Type::Int}};
case 3:
return {{"gl_PointSize", Type::Float}};
}
return std::nullopt;
return {};
case Attribute::Index::FrontColor:
return {{"gl_FrontColor"s + GetSwizzle(element), Type::Float}};
case Attribute::Index::FrontSecondaryColor:
@@ -1332,7 +1332,7 @@ private:
Type::Float}};
}
UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute));
return std::nullopt;
return {};
}
}
@@ -1443,10 +1443,8 @@ private:
return expr + ", vec2(0.0), vec2(0.0))";
case TextureType::TextureCube:
return expr + ", vec3(0.0), vec3(0.0))";
default:
UNREACHABLE();
break;
}
UNREACHABLE();
}
for (const auto& variant : extras) {

Some files were not shown because too many files have changed in this diff Show More