Compare commits
9 Commits
android-27
...
android-27
Author | SHA1 | Date | |
---|---|---|---|
dffc08bd15 | |||
597a1da426 | |||
4052ffb97b | |||
29fa1417fa | |||
54737ce166 | |||
cb64ec8b78 | |||
c4b57450a1 | |||
26c9d345a2 | |||
7375bf85b8 |
@ -1,9 +1,13 @@
|
|||||||
| Pull Request | Commit | Title | Author | Merged? |
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|----|----|----|----|----|
|
|----|----|----|----|----|
|
||||||
| [12461](https://github.com/yuzu-emu/yuzu//pull/12461) | [`a84e8e26f`](https://github.com/yuzu-emu/yuzu//pull/12461/files) | Rework Nvdec and VIC to fix out-of-order videos, and speed up decoding. | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
| [12461](https://github.com/yuzu-emu/yuzu//pull/12461) | [`a84e8e26f`](https://github.com/yuzu-emu/yuzu//pull/12461/files) | Rework Nvdec and VIC to fix out-of-order videos, and speed up decoding. | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
||||||
|
| [12749](https://github.com/yuzu-emu/yuzu//pull/12749) | [`aad4b0d6f`](https://github.com/yuzu-emu/yuzu//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [13018](https://github.com/yuzu-emu/yuzu//pull/13018) | [`01cbc638a`](https://github.com/yuzu-emu/yuzu//pull/13018/files) | am: rewrite part 2 | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [13018](https://github.com/yuzu-emu/yuzu//pull/13018) | [`01cbc638a`](https://github.com/yuzu-emu/yuzu//pull/13018/files) | am: rewrite part 2 | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [13174](https://github.com/yuzu-emu/yuzu//pull/13174) | [`7d1284826`](https://github.com/yuzu-emu/yuzu//pull/13174/files) | glue/time: Remove global variables | [FearlessTobi](https://github.com/FearlessTobi/) | Yes |
|
| [13096](https://github.com/yuzu-emu/yuzu//pull/13096) | [`0a8759057`](https://github.com/yuzu-emu/yuzu//pull/13096/files) | texture_cache: use two-pass collection for costly load resources | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [13177](https://github.com/yuzu-emu/yuzu//pull/13177) | [`f5cc94f05`](https://github.com/yuzu-emu/yuzu//pull/13177/files) | vfs: misc performance improvements | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [13122](https://github.com/yuzu-emu/yuzu//pull/13122) | [`5dc08c7fe`](https://github.com/yuzu-emu/yuzu//pull/13122/files) | vk_rasterizer: flip scissor y on lower left origin mode | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
|
| [13135](https://github.com/yuzu-emu/yuzu//pull/13135) | [`fc6a87bba`](https://github.com/yuzu-emu/yuzu//pull/13135/files) | service: hid: Migrate HidServer to new IPC | [german77](https://github.com/german77/) | Yes |
|
||||||
|
| [13166](https://github.com/yuzu-emu/yuzu//pull/13166) | [`4eecad914`](https://github.com/yuzu-emu/yuzu//pull/13166/files) | buffer_cache: avoid overflow in usage tracker | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
|
| [13171](https://github.com/yuzu-emu/yuzu//pull/13171) | [`fd9ed54f2`](https://github.com/yuzu-emu/yuzu//pull/13171/files) | texture_cache: do not track invalid addresses | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
|
|
||||||
|
|
||||||
End of merge log. You can find the original README.md below the break.
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
@ -343,7 +343,7 @@ void SetColorConsoleBackendEnabled(bool enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||||
unsigned int line_num, const char* function, fmt::string_view format,
|
unsigned int line_num, const char* function, const char* format,
|
||||||
const fmt::format_args& args) {
|
const fmt::format_args& args) {
|
||||||
if (!initialization_in_progress_suppress_logging) {
|
if (!initialization_in_progress_suppress_logging) {
|
||||||
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
|
||||||
|
@ -24,12 +24,12 @@ constexpr const char* TrimSourcePath(std::string_view source) {
|
|||||||
|
|
||||||
/// Logs a message to the global logger, using fmt
|
/// Logs a message to the global logger, using fmt
|
||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||||
unsigned int line_num, const char* function, fmt::string_view format,
|
unsigned int line_num, const char* function, const char* format,
|
||||||
const fmt::format_args& args);
|
const fmt::format_args& args);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||||
const char* function, fmt::format_string<Args...> format, const Args&... args) {
|
const char* function, const char* format, const Args&... args) {
|
||||||
FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format,
|
FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format,
|
||||||
fmt::make_format_args(args...));
|
fmt::make_format_args(args...));
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@ AesXtsStorage::AesXtsStorage(VirtualFile base, const void* key1, const void* key
|
|||||||
ASSERT(iv_size == IvSize);
|
ASSERT(iv_size == IvSize);
|
||||||
ASSERT(Common::IsAligned(m_block_size, AesBlockSize));
|
ASSERT(Common::IsAligned(m_block_size, AesBlockSize));
|
||||||
|
|
||||||
std::memcpy(m_key.data() + 0, key1, KeySize / 2);
|
std::memcpy(m_key.data() + 0, key1, KeySize);
|
||||||
std::memcpy(m_key.data() + 0x10, key2, KeySize / 2);
|
std::memcpy(m_key.data() + 0x10, key2, KeySize);
|
||||||
std::memcpy(m_iv.data(), iv, IvSize);
|
std::memcpy(m_iv.data(), iv, IvSize);
|
||||||
|
|
||||||
m_cipher.emplace(m_key, Core::Crypto::Mode::XTS);
|
m_cipher.emplace(m_key, Core::Crypto::Mode::XTS);
|
||||||
|
@ -105,4 +105,12 @@ VirtualDir PartitionFilesystem::GetParentDirectory() const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PartitionFilesystem::PrintDebugInfo() const {
|
||||||
|
LOG_DEBUG(Service_FS, "Magic: {:.4}", pfs_header.magic);
|
||||||
|
LOG_DEBUG(Service_FS, "Files: {}", pfs_header.num_entries);
|
||||||
|
for (u32 i = 0; i < pfs_header.num_entries; i++) {
|
||||||
|
LOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes)", i,
|
||||||
|
pfs_files[i]->GetName(), pfs_files[i]->GetSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
@ -35,6 +35,7 @@ public:
|
|||||||
std::vector<VirtualDir> GetSubdirectories() const override;
|
std::vector<VirtualDir> GetSubdirectories() const override;
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
VirtualDir GetParentDirectory() const override;
|
VirtualDir GetParentDirectory() const override;
|
||||||
|
void PrintDebugInfo() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Header {
|
struct Header {
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
OffsetVfsFile::OffsetVfsFile(VirtualFile file_, std::size_t size_, std::size_t offset_,
|
OffsetVfsFile::OffsetVfsFile(VirtualFile file_, std::size_t size_, std::size_t offset_,
|
||||||
std::string name_)
|
std::string name_, VirtualDir parent_)
|
||||||
: file(file_), offset(offset_), size(size_), name(std::move(name_)) {}
|
: file(file_), offset(offset_), size(size_), name(std::move(name_)),
|
||||||
|
parent(parent_ == nullptr ? file->GetContainingDirectory() : std::move(parent_)) {}
|
||||||
|
|
||||||
OffsetVfsFile::~OffsetVfsFile() = default;
|
OffsetVfsFile::~OffsetVfsFile() = default;
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ bool OffsetVfsFile::Resize(std::size_t new_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VirtualDir OffsetVfsFile::GetContainingDirectory() const {
|
VirtualDir OffsetVfsFile::GetContainingDirectory() const {
|
||||||
return nullptr;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OffsetVfsFile::IsWritable() const {
|
bool OffsetVfsFile::IsWritable() const {
|
||||||
|
@ -16,7 +16,7 @@ namespace FileSys {
|
|||||||
class OffsetVfsFile : public VfsFile {
|
class OffsetVfsFile : public VfsFile {
|
||||||
public:
|
public:
|
||||||
OffsetVfsFile(VirtualFile file, std::size_t size, std::size_t offset = 0,
|
OffsetVfsFile(VirtualFile file, std::size_t size, std::size_t offset = 0,
|
||||||
std::string new_name = "");
|
std::string new_name = "", VirtualDir new_parent = nullptr);
|
||||||
~OffsetVfsFile() override;
|
~OffsetVfsFile() override;
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
@ -44,6 +44,7 @@ private:
|
|||||||
std::size_t offset;
|
std::size_t offset;
|
||||||
std::size_t size;
|
std::size_t size;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
VirtualDir parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
@ -76,7 +76,6 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size,
|
VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size,
|
||||||
std::optional<std::string> parent_path,
|
|
||||||
OpenMode perms) {
|
OpenMode perms) {
|
||||||
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
|
||||||
std::scoped_lock lk{list_lock};
|
std::scoped_lock lk{list_lock};
|
||||||
@ -95,14 +94,14 @@ VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::op
|
|||||||
this->InsertReferenceIntoListLocked(*reference);
|
this->InsertReferenceIntoListLocked(*reference);
|
||||||
|
|
||||||
auto file = std::shared_ptr<RealVfsFile>(
|
auto file = std::shared_ptr<RealVfsFile>(
|
||||||
new RealVfsFile(*this, std::move(reference), path, perms, size, std::move(parent_path)));
|
new RealVfsFile(*this, std::move(reference), path, perms, size));
|
||||||
cache[path] = file;
|
cache[path] = file;
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, OpenMode perms) {
|
VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, OpenMode perms) {
|
||||||
return OpenFileFromEntry(path_, {}, {}, perms);
|
return OpenFileFromEntry(path_, {}, perms);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, OpenMode perms) {
|
VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, OpenMode perms) {
|
||||||
@ -269,11 +268,10 @@ void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
|
RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
|
||||||
const std::string& path_, OpenMode perms_, std::optional<u64> size_,
|
const std::string& path_, OpenMode perms_, std::optional<u64> size_)
|
||||||
std::optional<std::string> parent_path_)
|
|
||||||
: base(base_), reference(std::move(reference_)), path(path_),
|
: base(base_), reference(std::move(reference_)), path(path_),
|
||||||
parent_path(parent_path_ ? std::move(*parent_path_) : FS::GetParentPath(path_)),
|
parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponentsCopy(path_)),
|
||||||
path_components(FS::SplitPathComponentsCopy(path_)), size(size_), perms(perms_) {}
|
size(size_), perms(perms_) {}
|
||||||
|
|
||||||
RealVfsFile::~RealVfsFile() {
|
RealVfsFile::~RealVfsFile() {
|
||||||
base.DropReference(std::move(reference));
|
base.DropReference(std::move(reference));
|
||||||
@ -350,7 +348,7 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>(
|
|||||||
&out](const std::filesystem::directory_entry& entry) {
|
&out](const std::filesystem::directory_entry& entry) {
|
||||||
const auto full_path_string = FS::PathToUTF8String(entry.path());
|
const auto full_path_string = FS::PathToUTF8String(entry.path());
|
||||||
|
|
||||||
out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), path, perms));
|
out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), perms));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -62,7 +62,6 @@ private:
|
|||||||
private:
|
private:
|
||||||
friend class RealVfsDirectory;
|
friend class RealVfsDirectory;
|
||||||
VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size,
|
VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size,
|
||||||
std::optional<std::string> parent_path,
|
|
||||||
OpenMode perms = OpenMode::Read);
|
OpenMode perms = OpenMode::Read);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -92,7 +91,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
|
RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
|
||||||
const std::string& path, OpenMode perms = OpenMode::Read,
|
const std::string& path, OpenMode perms = OpenMode::Read,
|
||||||
std::optional<u64> size = {}, std::optional<std::string> parent_path = {});
|
std::optional<u64> size = {});
|
||||||
|
|
||||||
RealVfsFilesystem& base;
|
RealVfsFilesystem& base;
|
||||||
std::unique_ptr<FileReference> reference;
|
std::unique_ptr<FileReference> reference;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "core/file_sys/vfs/vfs.h"
|
#include "core/file_sys/vfs/vfs.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
#include "core/hle/service/glue/time/manager.h"
|
#include "core/hle/service/glue/time/manager.h"
|
||||||
|
#include "core/hle/service/glue/time/time_zone_binary.h"
|
||||||
#include "core/hle/service/psc/time/service_manager.h"
|
#include "core/hle/service/psc/time/service_manager.h"
|
||||||
#include "core/hle/service/psc/time/static.h"
|
#include "core/hle/service/psc/time/static.h"
|
||||||
#include "core/hle/service/psc/time/system_clock.h"
|
#include "core/hle/service/psc/time/system_clock.h"
|
||||||
@ -19,8 +20,8 @@
|
|||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
|
namespace {
|
||||||
static s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
|
s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
|
||||||
constexpr auto is_leap = [](s32 year) -> bool {
|
constexpr auto is_leap = [](s32 year) -> bool {
|
||||||
return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0));
|
return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0));
|
||||||
};
|
};
|
||||||
@ -49,8 +50,7 @@ static s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
|
|||||||
return epoch_s - 62135683200ll;
|
return epoch_s - 62135683200ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s64 GetEpochTimeFromInitialYear(
|
s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) {
|
||||||
std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) {
|
|
||||||
s32 year{2000};
|
s32 year{2000};
|
||||||
set_sys->GetSettingsItemValueImpl(year, "time", "standard_user_clock_initial_year");
|
set_sys->GetSettingsItemValueImpl(year, "time", "standard_user_clock_initial_year");
|
||||||
|
|
||||||
@ -65,32 +65,31 @@ static s64 GetEpochTimeFromInitialYear(
|
|||||||
return CalendarTimeToEpoch(calendar);
|
return CalendarTimeToEpoch(calendar);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Service::PSC::Time::LocationName GetTimeZoneString(
|
Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationName& in_name) {
|
||||||
TimeZoneBinary& time_zone_binary, Service::PSC::Time::LocationName& in_name) {
|
|
||||||
auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
|
auto configured_zone = Settings::GetTimeZoneString(Settings::values.time_zone_index.GetValue());
|
||||||
|
|
||||||
Service::PSC::Time::LocationName configured_name{};
|
Service::PSC::Time::LocationName configured_name{};
|
||||||
std::memcpy(configured_name.data(), configured_zone.data(),
|
std::memcpy(configured_name.data(), configured_zone.data(),
|
||||||
std::min(configured_name.size(), configured_zone.size()));
|
std::min(configured_name.size(), configured_zone.size()));
|
||||||
|
|
||||||
if (!time_zone_binary.IsValid(configured_name)) {
|
if (!IsTimeZoneBinaryValid(configured_name)) {
|
||||||
configured_zone = Common::TimeZone::FindSystemTimeZone();
|
configured_zone = Common::TimeZone::FindSystemTimeZone();
|
||||||
configured_name = {};
|
configured_name = {};
|
||||||
std::memcpy(configured_name.data(), configured_zone.data(),
|
std::memcpy(configured_name.data(), configured_zone.data(),
|
||||||
std::min(configured_name.size(), configured_zone.size()));
|
std::min(configured_name.size(), configured_zone.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_MSG(time_zone_binary.IsValid(configured_name), "Invalid time zone {}!",
|
ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!",
|
||||||
configured_name.data());
|
configured_name.data());
|
||||||
|
|
||||||
return configured_name;
|
return configured_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
TimeManager::TimeManager(Core::System& system)
|
TimeManager::TimeManager(Core::System& system)
|
||||||
: m_steady_clock_resource{system}, m_time_zone_binary{system}, m_worker{
|
: m_steady_clock_resource{system}, m_worker{system, m_steady_clock_resource,
|
||||||
system,
|
m_file_timestamp_worker} {
|
||||||
m_steady_clock_resource,
|
|
||||||
m_file_timestamp_worker} {
|
|
||||||
m_time_m =
|
m_time_m =
|
||||||
system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true);
|
system.ServiceManager().GetService<Service::PSC::Time::ServiceManager>("time:m", true);
|
||||||
|
|
||||||
@ -100,7 +99,7 @@ TimeManager::TimeManager(Core::System& system)
|
|||||||
m_set_sys =
|
m_set_sys =
|
||||||
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
||||||
|
|
||||||
res = m_time_zone_binary.Mount();
|
res = MountTimeZoneBinary(system);
|
||||||
ASSERT(res == ResultSuccess);
|
ASSERT(res == ResultSuccess);
|
||||||
|
|
||||||
m_worker.Initialize(m_time_sm, m_set_sys);
|
m_worker.Initialize(m_time_sm, m_set_sys);
|
||||||
@ -188,6 +187,10 @@ TimeManager::TimeManager(Core::System& system)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeManager::~TimeManager() {
|
||||||
|
ResetTimeZoneBinary();
|
||||||
|
}
|
||||||
|
|
||||||
Result TimeManager::SetupStandardSteadyClockCore() {
|
Result TimeManager::SetupStandardSteadyClockCore() {
|
||||||
Common::UUID external_clock_source_id{};
|
Common::UUID external_clock_source_id{};
|
||||||
auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id);
|
auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id);
|
||||||
@ -233,7 +236,7 @@ Result TimeManager::SetupTimeZoneServiceCore() {
|
|||||||
auto res = m_set_sys->GetDeviceTimeZoneLocationName(&name);
|
auto res = m_set_sys->GetDeviceTimeZoneLocationName(&name);
|
||||||
ASSERT(res == ResultSuccess);
|
ASSERT(res == ResultSuccess);
|
||||||
|
|
||||||
auto configured_zone = GetTimeZoneString(m_time_zone_binary, name);
|
auto configured_zone = GetTimeZoneString(name);
|
||||||
|
|
||||||
if (configured_zone != name) {
|
if (configured_zone != name) {
|
||||||
m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
|
m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
|
||||||
@ -251,13 +254,13 @@ Result TimeManager::SetupTimeZoneServiceCore() {
|
|||||||
res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(&time_point);
|
res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(&time_point);
|
||||||
ASSERT(res == ResultSuccess);
|
ASSERT(res == ResultSuccess);
|
||||||
|
|
||||||
auto location_count = m_time_zone_binary.GetTimeZoneCount();
|
auto location_count = GetTimeZoneCount();
|
||||||
Service::PSC::Time::RuleVersion rule_version{};
|
Service::PSC::Time::RuleVersion rule_version{};
|
||||||
m_time_zone_binary.GetTimeZoneVersion(rule_version);
|
GetTimeZoneVersion(rule_version);
|
||||||
|
|
||||||
std::span<const u8> rule_buffer{};
|
std::span<const u8> rule_buffer{};
|
||||||
size_t rule_size{};
|
size_t rule_size{};
|
||||||
res = m_time_zone_binary.GetTimeZoneRule(rule_buffer, rule_size, name);
|
res = GetTimeZoneRule(rule_buffer, rule_size, name);
|
||||||
ASSERT(res == ResultSuccess);
|
ASSERT(res == ResultSuccess);
|
||||||
|
|
||||||
res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point,
|
res = m_time_m->SetupTimeZoneServiceCore(name, rule_version, location_count, time_point,
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include "core/file_sys/vfs/vfs_types.h"
|
#include "core/file_sys/vfs/vfs_types.h"
|
||||||
#include "core/hle/service/glue/time/file_timestamp_worker.h"
|
#include "core/hle/service/glue/time/file_timestamp_worker.h"
|
||||||
#include "core/hle/service/glue/time/standard_steady_clock_resource.h"
|
#include "core/hle/service/glue/time/standard_steady_clock_resource.h"
|
||||||
#include "core/hle/service/glue/time/time_zone_binary.h"
|
|
||||||
#include "core/hle/service/glue/time/worker.h"
|
#include "core/hle/service/glue/time/worker.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ namespace Service::Glue::Time {
|
|||||||
class TimeManager {
|
class TimeManager {
|
||||||
public:
|
public:
|
||||||
explicit TimeManager(Core::System& system);
|
explicit TimeManager(Core::System& system);
|
||||||
~TimeManager() = default;
|
~TimeManager();
|
||||||
|
|
||||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||||
|
|
||||||
@ -35,7 +34,6 @@ public:
|
|||||||
std::shared_ptr<Service::PSC::Time::StaticService> m_time_sm{};
|
std::shared_ptr<Service::PSC::Time::StaticService> m_time_sm{};
|
||||||
StandardSteadyClockResource m_steady_clock_resource;
|
StandardSteadyClockResource m_steady_clock_resource;
|
||||||
FileTimestampWorker m_file_timestamp_worker;
|
FileTimestampWorker m_file_timestamp_worker;
|
||||||
TimeZoneBinary m_time_zone_binary;
|
|
||||||
TimeWorker m_worker;
|
TimeWorker m_worker;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -26,9 +26,8 @@ StaticService::StaticService(Core::System& system_,
|
|||||||
std::shared_ptr<TimeManager> time, const char* name)
|
std::shared_ptr<TimeManager> time, const char* name)
|
||||||
: ServiceFramework{system_, name}, m_system{system_}, m_time_m{time->m_time_m},
|
: ServiceFramework{system_, name}, m_system{system_}, m_time_m{time->m_time_m},
|
||||||
m_setup_info{setup_info}, m_time_sm{time->m_time_sm},
|
m_setup_info{setup_info}, m_time_sm{time->m_time_sm},
|
||||||
m_file_timestamp_worker{time->m_file_timestamp_worker},
|
m_file_timestamp_worker{time->m_file_timestamp_worker}, m_standard_steady_clock_resource{
|
||||||
m_standard_steady_clock_resource{time->m_steady_clock_resource},
|
time->m_steady_clock_resource} {
|
||||||
m_time_zone_binary{time->m_time_zone_binary} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
|
{0, D<&StaticService::GetStandardUserSystemClock>, "GetStandardUserSystemClock"},
|
||||||
@ -107,7 +106,7 @@ Result StaticService::GetTimeZoneService(OutInterface<TimeZoneService> out_servi
|
|||||||
|
|
||||||
*out_service = std::make_shared<TimeZoneService>(
|
*out_service = std::make_shared<TimeZoneService>(
|
||||||
m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location,
|
m_system, m_file_timestamp_worker, m_setup_info.can_write_timezone_device_location,
|
||||||
m_time_zone_binary, m_time_zone);
|
m_time_zone);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,5 @@ private:
|
|||||||
std::shared_ptr<Service::PSC::Time::TimeZoneService> m_time_zone;
|
std::shared_ptr<Service::PSC::Time::TimeZoneService> m_time_zone;
|
||||||
FileTimestampWorker& m_file_timestamp_worker;
|
FileTimestampWorker& m_file_timestamp_worker;
|
||||||
StandardSteadyClockResource& m_standard_steady_clock_resource;
|
StandardSteadyClockResource& m_standard_steady_clock_resource;
|
||||||
TimeZoneBinary& m_time_zone_binary;
|
|
||||||
};
|
};
|
||||||
} // namespace Service::Glue::Time
|
} // namespace Service::Glue::Time
|
||||||
|
@ -15,16 +15,19 @@
|
|||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
|
namespace {
|
||||||
|
static std::mutex g_list_mutex;
|
||||||
|
static Common::IntrusiveListBaseTraits<Service::PSC::Time::OperationEvent>::ListType g_list_nodes{};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
TimeZoneService::TimeZoneService(
|
TimeZoneService::TimeZoneService(
|
||||||
Core::System& system_, FileTimestampWorker& file_timestamp_worker,
|
Core::System& system_, FileTimestampWorker& file_timestamp_worker,
|
||||||
bool can_write_timezone_device_location, TimeZoneBinary& time_zone_binary,
|
bool can_write_timezone_device_location,
|
||||||
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service)
|
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service)
|
||||||
: ServiceFramework{system_, "ITimeZoneService"}, m_system{system},
|
: ServiceFramework{system_, "ITimeZoneService"}, m_system{system},
|
||||||
m_can_write_timezone_device_location{can_write_timezone_device_location},
|
m_can_write_timezone_device_location{can_write_timezone_device_location},
|
||||||
m_file_timestamp_worker{file_timestamp_worker}, m_wrapped_service{std::move(
|
m_file_timestamp_worker{file_timestamp_worker},
|
||||||
time_zone_service)},
|
m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} {
|
||||||
m_operation_event{m_system}, m_time_zone_binary{time_zone_binary} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
{0, D<&TimeZoneService::GetDeviceLocationName>, "GetDeviceLocationName"},
|
||||||
@ -45,6 +48,7 @@ TimeZoneService::TimeZoneService(
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
g_list_nodes.clear();
|
||||||
m_set_sys =
|
m_set_sys =
|
||||||
m_system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
m_system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
||||||
}
|
}
|
||||||
@ -65,13 +69,13 @@ Result TimeZoneService::SetDeviceLocationName(
|
|||||||
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
|
LOG_DEBUG(Service_Time, "called. location_name={}", location_name);
|
||||||
|
|
||||||
R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
|
R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied);
|
||||||
R_UNLESS(m_time_zone_binary.IsValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound);
|
R_UNLESS(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound);
|
||||||
|
|
||||||
std::scoped_lock l{m_mutex};
|
std::scoped_lock l{m_mutex};
|
||||||
|
|
||||||
std::span<const u8> binary{};
|
std::span<const u8> binary{};
|
||||||
size_t binary_size{};
|
size_t binary_size{};
|
||||||
R_TRY(m_time_zone_binary.GetTimeZoneRule(binary, binary_size, location_name))
|
R_TRY(GetTimeZoneRule(binary, binary_size, location_name))
|
||||||
|
|
||||||
R_TRY(m_wrapped_service->SetDeviceLocationNameWithTimeZoneRule(location_name, binary));
|
R_TRY(m_wrapped_service->SetDeviceLocationNameWithTimeZoneRule(location_name, binary));
|
||||||
|
|
||||||
@ -84,8 +88,8 @@ Result TimeZoneService::SetDeviceLocationName(
|
|||||||
m_set_sys->SetDeviceTimeZoneLocationName(name);
|
m_set_sys->SetDeviceTimeZoneLocationName(name);
|
||||||
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point);
|
m_set_sys->SetDeviceTimeZoneLocationUpdatedTime(time_point);
|
||||||
|
|
||||||
std::scoped_lock m{m_list_mutex};
|
std::scoped_lock m{g_list_mutex};
|
||||||
for (auto& operation_event : m_list_nodes) {
|
for (auto& operation_event : g_list_nodes) {
|
||||||
operation_event.m_event->Signal();
|
operation_event.m_event->Signal();
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -108,8 +112,7 @@ Result TimeZoneService::LoadLocationNameList(
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::scoped_lock l{m_mutex};
|
std::scoped_lock l{m_mutex};
|
||||||
R_RETURN(
|
R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index));
|
||||||
m_time_zone_binary.GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule,
|
Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule,
|
||||||
@ -119,7 +122,7 @@ Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule,
|
|||||||
std::scoped_lock l{m_mutex};
|
std::scoped_lock l{m_mutex};
|
||||||
std::span<const u8> binary{};
|
std::span<const u8> binary{};
|
||||||
size_t binary_size{};
|
size_t binary_size{};
|
||||||
R_TRY(m_time_zone_binary.GetTimeZoneRule(binary, binary_size, name))
|
R_TRY(GetTimeZoneRule(binary, binary_size, name))
|
||||||
R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
|
R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +174,7 @@ Result TimeZoneService::GetDeviceLocationNameOperationEventReadableHandle(
|
|||||||
m_operation_event.m_ctx.CreateEvent("Psc:TimeZoneService:OperationEvent");
|
m_operation_event.m_ctx.CreateEvent("Psc:TimeZoneService:OperationEvent");
|
||||||
operation_event_initialized = true;
|
operation_event_initialized = true;
|
||||||
std::scoped_lock l{m_mutex};
|
std::scoped_lock l{m_mutex};
|
||||||
m_list_nodes.push_back(m_operation_event);
|
g_list_nodes.push_back(m_operation_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_event = &m_operation_event.m_event->GetReadableEvent();
|
*out_event = &m_operation_event.m_event->GetReadableEvent();
|
||||||
|
@ -32,7 +32,6 @@ class TimeZoneService;
|
|||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
class FileTimestampWorker;
|
class FileTimestampWorker;
|
||||||
class TimeZoneBinary;
|
|
||||||
|
|
||||||
class TimeZoneService final : public ServiceFramework<TimeZoneService> {
|
class TimeZoneService final : public ServiceFramework<TimeZoneService> {
|
||||||
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
using InRule = InLargeData<Tz::Rule, BufferAttr_HipcMapAlias>;
|
||||||
@ -41,7 +40,7 @@ class TimeZoneService final : public ServiceFramework<TimeZoneService> {
|
|||||||
public:
|
public:
|
||||||
explicit TimeZoneService(
|
explicit TimeZoneService(
|
||||||
Core::System& system, FileTimestampWorker& file_timestamp_worker,
|
Core::System& system, FileTimestampWorker& file_timestamp_worker,
|
||||||
bool can_write_timezone_device_location, TimeZoneBinary& time_zone_binary,
|
bool can_write_timezone_device_location,
|
||||||
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service);
|
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service);
|
||||||
|
|
||||||
~TimeZoneService() override;
|
~TimeZoneService() override;
|
||||||
@ -86,10 +85,6 @@ private:
|
|||||||
std::mutex m_mutex;
|
std::mutex m_mutex;
|
||||||
bool operation_event_initialized{};
|
bool operation_event_initialized{};
|
||||||
Service::PSC::Time::OperationEvent m_operation_event;
|
Service::PSC::Time::OperationEvent m_operation_event;
|
||||||
TimeZoneBinary& m_time_zone_binary;
|
|
||||||
|
|
||||||
std::mutex m_list_mutex;
|
|
||||||
Common::IntrusiveListBaseTraits<Service::PSC::Time::OperationEvent>::ListType m_list_nodes{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Glue::Time
|
} // namespace Service::Glue::Time
|
||||||
|
@ -12,58 +12,18 @@
|
|||||||
#include "core/hle/service/glue/time/time_zone_binary.h"
|
#include "core/hle/service/glue/time/time_zone_binary.h"
|
||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
|
namespace {
|
||||||
constexpr u64 TimeZoneBinaryId = 0x10000000000080E;
|
constexpr u64 TimeZoneBinaryId = 0x10000000000080E;
|
||||||
|
|
||||||
void TimeZoneBinary::Reset() {
|
static FileSys::VirtualDir g_time_zone_binary_romfs{};
|
||||||
time_zone_binary_romfs = {};
|
static Result g_time_zone_binary_mount_result{ResultUnknown};
|
||||||
time_zone_binary_mount_result = ResultUnknown;
|
static std::vector<u8> g_time_zone_scratch_space(0x2800, 0);
|
||||||
time_zone_scratch_space.clear();
|
|
||||||
time_zone_scratch_space.resize(0x2800, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result TimeZoneBinary::Mount() {
|
Result TimeZoneReadBinary(size_t& out_read_size, std::span<u8> out_buffer, size_t out_buffer_size,
|
||||||
Reset();
|
std::string_view path) {
|
||||||
|
R_UNLESS(g_time_zone_binary_mount_result == ResultSuccess, g_time_zone_binary_mount_result);
|
||||||
|
|
||||||
auto& fsc{system.GetFileSystemController()};
|
auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)};
|
||||||
std::unique_ptr<FileSys::NCA> nca{};
|
|
||||||
|
|
||||||
auto* bis_system = fsc.GetSystemNANDContents();
|
|
||||||
|
|
||||||
R_UNLESS(bis_system, ResultUnknown);
|
|
||||||
|
|
||||||
nca = bis_system->GetEntry(TimeZoneBinaryId, FileSys::ContentRecordType::Data);
|
|
||||||
|
|
||||||
if (nca) {
|
|
||||||
time_zone_binary_romfs = FileSys::ExtractRomFS(nca->GetRomFS());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (time_zone_binary_romfs) {
|
|
||||||
// Validate that the romfs is readable, using invalid firmware keys can cause this to get
|
|
||||||
// set but the files to be garbage. In that case, we want to hit the next path and
|
|
||||||
// synthesise them instead.
|
|
||||||
time_zone_binary_mount_result = ResultSuccess;
|
|
||||||
Service::PSC::Time::LocationName name{"Etc/GMT"};
|
|
||||||
if (!IsValid(name)) {
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!time_zone_binary_romfs) {
|
|
||||||
time_zone_binary_romfs = FileSys::ExtractRomFS(
|
|
||||||
FileSys::SystemArchive::SynthesizeSystemArchive(TimeZoneBinaryId));
|
|
||||||
}
|
|
||||||
|
|
||||||
R_UNLESS(time_zone_binary_romfs, ResultUnknown);
|
|
||||||
|
|
||||||
time_zone_binary_mount_result = ResultSuccess;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result TimeZoneBinary::Read(size_t& out_read_size, std::span<u8> out_buffer, size_t out_buffer_size,
|
|
||||||
std::string_view path) {
|
|
||||||
R_UNLESS(time_zone_binary_mount_result == ResultSuccess, time_zone_binary_mount_result);
|
|
||||||
|
|
||||||
auto vfs_file{time_zone_binary_romfs->GetFileRelative(path)};
|
|
||||||
R_UNLESS(vfs_file, ResultUnknown);
|
R_UNLESS(vfs_file, ResultUnknown);
|
||||||
|
|
||||||
auto file_size{vfs_file->GetSize()};
|
auto file_size{vfs_file->GetSize()};
|
||||||
@ -76,37 +36,82 @@ Result TimeZoneBinary::Read(size_t& out_read_size, std::span<u8> out_buffer, siz
|
|||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void TimeZoneBinary::GetListPath(std::string& out_path) {
|
void ResetTimeZoneBinary() {
|
||||||
if (time_zone_binary_mount_result != ResultSuccess) {
|
g_time_zone_binary_romfs = {};
|
||||||
|
g_time_zone_binary_mount_result = ResultUnknown;
|
||||||
|
g_time_zone_scratch_space.clear();
|
||||||
|
g_time_zone_scratch_space.resize(0x2800, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result MountTimeZoneBinary(Core::System& system) {
|
||||||
|
ResetTimeZoneBinary();
|
||||||
|
|
||||||
|
auto& fsc{system.GetFileSystemController()};
|
||||||
|
std::unique_ptr<FileSys::NCA> nca{};
|
||||||
|
|
||||||
|
auto* bis_system = fsc.GetSystemNANDContents();
|
||||||
|
|
||||||
|
R_UNLESS(bis_system, ResultUnknown);
|
||||||
|
|
||||||
|
nca = bis_system->GetEntry(TimeZoneBinaryId, FileSys::ContentRecordType::Data);
|
||||||
|
|
||||||
|
if (nca) {
|
||||||
|
g_time_zone_binary_romfs = FileSys::ExtractRomFS(nca->GetRomFS());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_time_zone_binary_romfs) {
|
||||||
|
// Validate that the romfs is readable, using invalid firmware keys can cause this to get
|
||||||
|
// set but the files to be garbage. In that case, we want to hit the next path and
|
||||||
|
// synthesise them instead.
|
||||||
|
g_time_zone_binary_mount_result = ResultSuccess;
|
||||||
|
Service::PSC::Time::LocationName name{"Etc/GMT"};
|
||||||
|
if (!IsTimeZoneBinaryValid(name)) {
|
||||||
|
ResetTimeZoneBinary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_time_zone_binary_romfs) {
|
||||||
|
g_time_zone_binary_romfs = FileSys::ExtractRomFS(
|
||||||
|
FileSys::SystemArchive::SynthesizeSystemArchive(TimeZoneBinaryId));
|
||||||
|
}
|
||||||
|
|
||||||
|
R_UNLESS(g_time_zone_binary_romfs, ResultUnknown);
|
||||||
|
|
||||||
|
g_time_zone_binary_mount_result = ResultSuccess;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetTimeZoneBinaryListPath(std::string& out_path) {
|
||||||
|
if (g_time_zone_binary_mount_result != ResultSuccess) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// out_path = fmt::format("{}:/binaryList.txt", "TimeZoneBinary");
|
// out_path = fmt::format("{}:/binaryList.txt", "TimeZoneBinary");
|
||||||
out_path = "/binaryList.txt";
|
out_path = "/binaryList.txt";
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeZoneBinary::GetVersionPath(std::string& out_path) {
|
void GetTimeZoneBinaryVersionPath(std::string& out_path) {
|
||||||
if (time_zone_binary_mount_result != ResultSuccess) {
|
if (g_time_zone_binary_mount_result != ResultSuccess) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// out_path = fmt::format("{}:/version.txt", "TimeZoneBinary");
|
// out_path = fmt::format("{}:/version.txt", "TimeZoneBinary");
|
||||||
out_path = "/version.txt";
|
out_path = "/version.txt";
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeZoneBinary::GetTimeZonePath(std::string& out_path,
|
void GetTimeZoneZonePath(std::string& out_path, const Service::PSC::Time::LocationName& name) {
|
||||||
const Service::PSC::Time::LocationName& name) {
|
if (g_time_zone_binary_mount_result != ResultSuccess) {
|
||||||
if (time_zone_binary_mount_result != ResultSuccess) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name);
|
// out_path = fmt::format("{}:/zoneinfo/{}", "TimeZoneBinary", name);
|
||||||
out_path = fmt::format("/zoneinfo/{}", name.data());
|
out_path = fmt::format("/zoneinfo/{}", name.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TimeZoneBinary::IsValid(const Service::PSC::Time::LocationName& name) {
|
bool IsTimeZoneBinaryValid(const Service::PSC::Time::LocationName& name) {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetTimeZonePath(path, name);
|
GetTimeZoneZonePath(path, name);
|
||||||
|
|
||||||
auto vfs_file{time_zone_binary_romfs->GetFileRelative(path)};
|
auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)};
|
||||||
if (!vfs_file) {
|
if (!vfs_file) {
|
||||||
LOG_INFO(Service_Time, "Could not find timezone file {}", path);
|
LOG_INFO(Service_Time, "Could not find timezone file {}", path);
|
||||||
return false;
|
return false;
|
||||||
@ -114,19 +119,19 @@ bool TimeZoneBinary::IsValid(const Service::PSC::Time::LocationName& name) {
|
|||||||
return vfs_file->GetSize() != 0;
|
return vfs_file->GetSize() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 TimeZoneBinary::GetTimeZoneCount() {
|
u32 GetTimeZoneCount() {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetListPath(path);
|
GetTimeZoneBinaryListPath(path);
|
||||||
|
|
||||||
size_t bytes_read{};
|
size_t bytes_read{};
|
||||||
if (Read(bytes_read, time_zone_scratch_space, 0x2800, path) != ResultSuccess) {
|
if (TimeZoneReadBinary(bytes_read, g_time_zone_scratch_space, 0x2800, path) != ResultSuccess) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (bytes_read == 0) {
|
if (bytes_read == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto chars = std::span(reinterpret_cast<char*>(time_zone_scratch_space.data()), bytes_read);
|
auto chars = std::span(reinterpret_cast<char*>(g_time_zone_scratch_space.data()), bytes_read);
|
||||||
u32 count{};
|
u32 count{};
|
||||||
for (auto chr : chars) {
|
for (auto chr : chars) {
|
||||||
if (chr == '\n') {
|
if (chr == '\n') {
|
||||||
@ -136,47 +141,50 @@ u32 TimeZoneBinary::GetTimeZoneCount() {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZoneBinary::GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version) {
|
Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version) {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetVersionPath(path);
|
GetTimeZoneBinaryVersionPath(path);
|
||||||
|
|
||||||
auto rule_version_buffer{std::span(reinterpret_cast<u8*>(&out_rule_version),
|
auto rule_version_buffer{std::span(reinterpret_cast<u8*>(&out_rule_version),
|
||||||
sizeof(Service::PSC::Time::RuleVersion))};
|
sizeof(Service::PSC::Time::RuleVersion))};
|
||||||
size_t bytes_read{};
|
size_t bytes_read{};
|
||||||
R_TRY(Read(bytes_read, rule_version_buffer, rule_version_buffer.size_bytes(), path));
|
R_TRY(TimeZoneReadBinary(bytes_read, rule_version_buffer, rule_version_buffer.size_bytes(),
|
||||||
|
path));
|
||||||
|
|
||||||
rule_version_buffer[bytes_read] = 0;
|
rule_version_buffer[bytes_read] = 0;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZoneBinary::GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
|
Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
|
||||||
const Service::PSC::Time::LocationName& name) {
|
const Service::PSC::Time::LocationName& name) {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetTimeZonePath(path, name);
|
GetTimeZoneZonePath(path, name);
|
||||||
|
|
||||||
size_t bytes_read{};
|
size_t bytes_read{};
|
||||||
R_TRY(Read(bytes_read, time_zone_scratch_space, time_zone_scratch_space.size(), path));
|
R_TRY(TimeZoneReadBinary(bytes_read, g_time_zone_scratch_space,
|
||||||
|
g_time_zone_scratch_space.size(), path));
|
||||||
|
|
||||||
out_rule = std::span(time_zone_scratch_space.data(), bytes_read);
|
out_rule = std::span(g_time_zone_scratch_space.data(), bytes_read);
|
||||||
out_rule_size = bytes_read;
|
out_rule_size = bytes_read;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TimeZoneBinary::GetTimeZoneLocationList(
|
Result GetTimeZoneLocationList(u32& out_count,
|
||||||
u32& out_count, std::span<Service::PSC::Time::LocationName> out_names, size_t max_names,
|
std::span<Service::PSC::Time::LocationName> out_names,
|
||||||
u32 index) {
|
size_t max_names, u32 index) {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetListPath(path);
|
GetTimeZoneBinaryListPath(path);
|
||||||
|
|
||||||
size_t bytes_read{};
|
size_t bytes_read{};
|
||||||
R_TRY(Read(bytes_read, time_zone_scratch_space, time_zone_scratch_space.size(), path));
|
R_TRY(TimeZoneReadBinary(bytes_read, g_time_zone_scratch_space,
|
||||||
|
g_time_zone_scratch_space.size(), path));
|
||||||
|
|
||||||
out_count = 0;
|
out_count = 0;
|
||||||
R_SUCCEED_IF(bytes_read == 0);
|
R_SUCCEED_IF(bytes_read == 0);
|
||||||
|
|
||||||
Service::PSC::Time::LocationName current_name{};
|
Service::PSC::Time::LocationName current_name{};
|
||||||
size_t current_name_len{};
|
size_t current_name_len{};
|
||||||
std::span<const u8> chars{time_zone_scratch_space};
|
std::span<const u8> chars{g_time_zone_scratch_space};
|
||||||
u32 name_count{};
|
u32 name_count{};
|
||||||
|
|
||||||
for (auto chr : chars) {
|
for (auto chr : chars) {
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "core/hle/service/psc/time/common.h"
|
#include "core/hle/service/psc/time/common.h"
|
||||||
|
|
||||||
@ -16,34 +15,18 @@ class System;
|
|||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
|
|
||||||
class TimeZoneBinary {
|
void ResetTimeZoneBinary();
|
||||||
public:
|
Result MountTimeZoneBinary(Core::System& system);
|
||||||
explicit TimeZoneBinary(Core::System& system_)
|
void GetTimeZoneBinaryListPath(std::string& out_path);
|
||||||
: time_zone_scratch_space(0x2800, 0), system{system_} {}
|
void GetTimeZoneBinaryVersionPath(std::string& out_path);
|
||||||
|
void GetTimeZoneZonePath(std::string& out_path, const Service::PSC::Time::LocationName& name);
|
||||||
Result Mount();
|
bool IsTimeZoneBinaryValid(const Service::PSC::Time::LocationName& name);
|
||||||
bool IsValid(const Service::PSC::Time::LocationName& name);
|
u32 GetTimeZoneCount();
|
||||||
u32 GetTimeZoneCount();
|
Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version);
|
||||||
Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version);
|
Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
|
||||||
Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
|
const Service::PSC::Time::LocationName& name);
|
||||||
const Service::PSC::Time::LocationName& name);
|
Result GetTimeZoneLocationList(u32& out_count,
|
||||||
Result GetTimeZoneLocationList(u32& out_count,
|
std::span<Service::PSC::Time::LocationName> out_names,
|
||||||
std::span<Service::PSC::Time::LocationName> out_names,
|
size_t max_names, u32 index);
|
||||||
size_t max_names, u32 index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Reset();
|
|
||||||
Result Read(size_t& out_read_size, std::span<u8> out_buffer, size_t out_buffer_size,
|
|
||||||
std::string_view path);
|
|
||||||
void GetListPath(std::string& out_path);
|
|
||||||
void GetVersionPath(std::string& out_path);
|
|
||||||
void GetTimeZonePath(std::string& out_path, const Service::PSC::Time::LocationName& name);
|
|
||||||
|
|
||||||
FileSys::VirtualDir time_zone_binary_romfs{};
|
|
||||||
Result time_zone_binary_mount_result{ResultUnknown};
|
|
||||||
std::vector<u8> time_zone_scratch_space;
|
|
||||||
|
|
||||||
Core::System& system;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Service::Glue::Time
|
} // namespace Service::Glue::Time
|
||||||
|
@ -16,6 +16,23 @@
|
|||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool g_ig_report_network_clock_context_set{};
|
||||||
|
Service::PSC::Time::SystemClockContext g_report_network_clock_context{};
|
||||||
|
bool g_ig_report_ephemeral_clock_context_set{};
|
||||||
|
Service::PSC::Time::SystemClockContext g_report_ephemeral_clock_context{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys,
|
||||||
|
const char* category, const char* name) {
|
||||||
|
T v{};
|
||||||
|
auto res = set_sys->GetSettingsItemValueImpl(v, category, name);
|
||||||
|
ASSERT(res == ResultSuccess);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
|
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
|
||||||
FileTimestampWorker& file_timestamp_worker)
|
FileTimestampWorker& file_timestamp_worker)
|
||||||
@ -26,6 +43,11 @@ TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady
|
|||||||
"Glue:TimeWorker:SteadyClockTimerEvent")},
|
"Glue:TimeWorker:SteadyClockTimerEvent")},
|
||||||
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
|
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
|
||||||
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
|
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
|
||||||
|
g_ig_report_network_clock_context_set = false;
|
||||||
|
g_report_network_clock_context = {};
|
||||||
|
g_ig_report_ephemeral_clock_context_set = false;
|
||||||
|
g_report_ephemeral_clock_context = {};
|
||||||
|
|
||||||
m_timer_steady_clock_timing_event = Core::Timing::CreateEvent(
|
m_timer_steady_clock_timing_event = Core::Timing::CreateEvent(
|
||||||
"Time::SteadyClockEvent",
|
"Time::SteadyClockEvent",
|
||||||
[this](s64 time,
|
[this](s64 time,
|
||||||
@ -60,14 +82,6 @@ TimeWorker::~TimeWorker() {
|
|||||||
m_ctx.CloseEvent(m_timer_file_system);
|
m_ctx.CloseEvent(m_timer_file_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T TimeWorker::GetSettingsItemValue(const std::string& category, const std::string& name) {
|
|
||||||
T v{};
|
|
||||||
auto res = m_set_sys->GetSettingsItemValueImpl(v, category, name);
|
|
||||||
ASSERT(res == ResultSuccess);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> time_sm,
|
void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> time_sm,
|
||||||
std::shared_ptr<Service::Set::ISystemSettingsServer> set_sys) {
|
std::shared_ptr<Service::Set::ISystemSettingsServer> set_sys) {
|
||||||
m_set_sys = std::move(set_sys);
|
m_set_sys = std::move(set_sys);
|
||||||
@ -77,8 +91,8 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t
|
|||||||
|
|
||||||
m_alarm_worker.Initialize(m_time_m);
|
m_alarm_worker.Initialize(m_time_m);
|
||||||
|
|
||||||
auto steady_clock_interval_m =
|
auto steady_clock_interval_m = GetSettingsItemValue<s32>(
|
||||||
GetSettingsItemValue<s32>("time", "standard_steady_clock_rtc_update_interval_minutes");
|
m_set_sys, "time", "standard_steady_clock_rtc_update_interval_minutes");
|
||||||
|
|
||||||
auto one_minute_ns{
|
auto one_minute_ns{
|
||||||
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()};
|
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()};
|
||||||
@ -88,7 +102,8 @@ void TimeWorker::Initialize(std::shared_ptr<Service::PSC::Time::StaticService> t
|
|||||||
std::chrono::nanoseconds(steady_clock_interval_ns),
|
std::chrono::nanoseconds(steady_clock_interval_ns),
|
||||||
m_timer_steady_clock_timing_event);
|
m_timer_steady_clock_timing_event);
|
||||||
|
|
||||||
auto fs_notify_time_s = GetSettingsItemValue<s32>("time", "notify_time_to_fs_interval_seconds");
|
auto fs_notify_time_s =
|
||||||
|
GetSettingsItemValue<s32>(m_set_sys, "time", "notify_time_to_fs_interval_seconds");
|
||||||
auto one_second_ns{
|
auto one_second_ns{
|
||||||
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()};
|
std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::seconds(1)).count()};
|
||||||
s64 fs_notify_time_ns{fs_notify_time_s * one_second_ns};
|
s64 fs_notify_time_ns{fs_notify_time_s * one_second_ns};
|
||||||
@ -203,14 +218,14 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] auto offset_before{
|
[[maybe_unused]] auto offset_before{
|
||||||
m_ig_report_network_clock_context_set ? m_report_network_clock_context.offset : 0};
|
g_ig_report_network_clock_context_set ? g_report_network_clock_context.offset : 0};
|
||||||
// TODO system report "standard_netclock_operation"
|
// TODO system report "standard_netclock_operation"
|
||||||
// "clock_time" = time
|
// "clock_time" = time
|
||||||
// "context_offset_before" = offset_before
|
// "context_offset_before" = offset_before
|
||||||
// "context_offset_after" = context.offset
|
// "context_offset_after" = context.offset
|
||||||
m_report_network_clock_context = context;
|
g_report_network_clock_context = context;
|
||||||
if (!m_ig_report_network_clock_context_set) {
|
if (!g_ig_report_network_clock_context_set) {
|
||||||
m_ig_report_network_clock_context_set = true;
|
g_ig_report_network_clock_context_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file_timestamp_worker.SetFilesystemPosixTime();
|
m_file_timestamp_worker.SetFilesystemPosixTime();
|
||||||
@ -232,16 +247,16 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] auto offset_before{m_ig_report_ephemeral_clock_context_set
|
[[maybe_unused]] auto offset_before{g_ig_report_ephemeral_clock_context_set
|
||||||
? m_report_ephemeral_clock_context.offset
|
? g_report_ephemeral_clock_context.offset
|
||||||
: 0};
|
: 0};
|
||||||
// TODO system report "ephemeral_netclock_operation"
|
// TODO system report "ephemeral_netclock_operation"
|
||||||
// "clock_time" = time
|
// "clock_time" = time
|
||||||
// "context_offset_before" = offset_before
|
// "context_offset_before" = offset_before
|
||||||
// "context_offset_after" = context.offset
|
// "context_offset_after" = context.offset
|
||||||
m_report_ephemeral_clock_context = context;
|
g_report_ephemeral_clock_context = context;
|
||||||
if (!m_ig_report_ephemeral_clock_context_set) {
|
if (!g_ig_report_ephemeral_clock_context_set) {
|
||||||
m_ig_report_ephemeral_clock_context_set = true;
|
g_ig_report_ephemeral_clock_context_set = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,6 @@ public:
|
|||||||
void StartThread();
|
void StartThread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename T>
|
|
||||||
T GetSettingsItemValue(const std::string& category, const std::string& name);
|
|
||||||
|
|
||||||
void ThreadFunc(std::stop_token stop_token);
|
void ThreadFunc(std::stop_token stop_token);
|
||||||
|
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
@ -62,11 +59,6 @@ private:
|
|||||||
std::shared_ptr<Core::Timing::EventType> m_timer_file_system_timing_event;
|
std::shared_ptr<Core::Timing::EventType> m_timer_file_system_timing_event;
|
||||||
AlarmWorker m_alarm_worker;
|
AlarmWorker m_alarm_worker;
|
||||||
PmStateChangeHandler m_pm_state_change_handler;
|
PmStateChangeHandler m_pm_state_change_handler;
|
||||||
|
|
||||||
bool m_ig_report_network_clock_context_set{};
|
|
||||||
Service::PSC::Time::SystemClockContext m_report_network_clock_context{};
|
|
||||||
bool m_ig_report_ephemeral_clock_context_set{};
|
|
||||||
Service::PSC::Time::SystemClockContext m_report_ephemeral_clock_context{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Glue::Time
|
} // namespace Service::Glue::Time
|
||||||
|
@ -93,19 +93,13 @@ ServerManager::~ServerManager() {
|
|||||||
m_threads.clear();
|
m_threads.clear();
|
||||||
|
|
||||||
// Clean up ports.
|
// Clean up ports.
|
||||||
auto port_it = m_servers.begin();
|
for (auto it = m_servers.begin(); it != m_servers.end(); it = m_servers.erase(it)) {
|
||||||
while (port_it != m_servers.end()) {
|
delete std::addressof(*it);
|
||||||
auto* const port = std::addressof(*port_it);
|
|
||||||
port_it = m_servers.erase(port_it);
|
|
||||||
delete port;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up sessions.
|
// Clean up sessions.
|
||||||
auto session_it = m_sessions.begin();
|
for (auto it = m_sessions.begin(); it != m_sessions.end(); it = m_sessions.erase(it)) {
|
||||||
while (session_it != m_sessions.end()) {
|
delete std::addressof(*it);
|
||||||
auto* const session = std::addressof(*session_it);
|
|
||||||
session_it = m_sessions.erase(session_it);
|
|
||||||
delete session;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close wakeup event.
|
// Close wakeup event.
|
||||||
|
@ -36,23 +36,22 @@ std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FileType IdentifyFile(FileSys::VirtualFile file) {
|
FileType IdentifyFile(FileSys::VirtualFile file) {
|
||||||
if (const auto nsp_type = IdentifyFileLoader<AppLoader_NSP>(file)) {
|
if (const auto romdir_type = IdentifyFileLoader<AppLoader_DeconstructedRomDirectory>(file)) {
|
||||||
return *nsp_type;
|
return *romdir_type;
|
||||||
} else if (const auto xci_type = IdentifyFileLoader<AppLoader_XCI>(file)) {
|
} else if (const auto nso_type = IdentifyFileLoader<AppLoader_NSO>(file)) {
|
||||||
return *xci_type;
|
return *nso_type;
|
||||||
} else if (const auto nro_type = IdentifyFileLoader<AppLoader_NRO>(file)) {
|
} else if (const auto nro_type = IdentifyFileLoader<AppLoader_NRO>(file)) {
|
||||||
return *nro_type;
|
return *nro_type;
|
||||||
} else if (const auto nca_type = IdentifyFileLoader<AppLoader_NCA>(file)) {
|
} else if (const auto nca_type = IdentifyFileLoader<AppLoader_NCA>(file)) {
|
||||||
return *nca_type;
|
return *nca_type;
|
||||||
|
} else if (const auto xci_type = IdentifyFileLoader<AppLoader_XCI>(file)) {
|
||||||
|
return *xci_type;
|
||||||
} else if (const auto nax_type = IdentifyFileLoader<AppLoader_NAX>(file)) {
|
} else if (const auto nax_type = IdentifyFileLoader<AppLoader_NAX>(file)) {
|
||||||
return *nax_type;
|
return *nax_type;
|
||||||
|
} else if (const auto nsp_type = IdentifyFileLoader<AppLoader_NSP>(file)) {
|
||||||
|
return *nsp_type;
|
||||||
} else if (const auto kip_type = IdentifyFileLoader<AppLoader_KIP>(file)) {
|
} else if (const auto kip_type = IdentifyFileLoader<AppLoader_KIP>(file)) {
|
||||||
return *kip_type;
|
return *kip_type;
|
||||||
} else if (const auto nso_type = IdentifyFileLoader<AppLoader_NSO>(file)) {
|
|
||||||
return *nso_type;
|
|
||||||
} else if (const auto romdir_type =
|
|
||||||
IdentifyFileLoader<AppLoader_DeconstructedRomDirectory>(file)) {
|
|
||||||
return *romdir_type;
|
|
||||||
} else {
|
} else {
|
||||||
return FileType::Unknown;
|
return FileType::Unknown;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ const char* GetType(GLenum type) {
|
|||||||
|
|
||||||
void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
|
void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
|
||||||
const GLchar* message, const void* user_param) {
|
const GLchar* message, const void* user_param) {
|
||||||
constexpr std::string_view format = "{} {} {}: {}";
|
const char format[] = "{} {} {}: {}";
|
||||||
const char* const str_source = GetSource(source);
|
const char* const str_source = GetSource(source);
|
||||||
const char* const str_type = GetType(type);
|
const char* const str_type = GetType(type);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user