early-access version 4175
This commit is contained in:
parent
f6fd2265b1
commit
90ca646c0d
24 changed files with 225 additions and 213 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 4174.
|
This is the source code for early-access 4175.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -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, const char* format,
|
unsigned int line_num, const char* function, fmt::string_view 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, const char* format,
|
unsigned int line_num, const char* function, fmt::string_view 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, const char* format, const Args&... args) {
|
const char* function, fmt::format_string<Args...> 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);
|
std::memcpy(m_key.data() + 0, key1, KeySize / 2);
|
||||||
std::memcpy(m_key.data() + 0x10, key2, KeySize);
|
std::memcpy(m_key.data() + 0x10, key2, KeySize / 2);
|
||||||
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,12 +105,4 @@ 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,7 +35,6 @@ 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,9 +9,8 @@
|
||||||
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_, VirtualDir parent_)
|
std::string name_)
|
||||||
: 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;
|
||||||
|
|
||||||
|
@ -37,7 +36,7 @@ bool OffsetVfsFile::Resize(std::size_t new_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualDir OffsetVfsFile::GetContainingDirectory() const {
|
VirtualDir OffsetVfsFile::GetContainingDirectory() const {
|
||||||
return parent;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = "", VirtualDir new_parent = nullptr);
|
std::string new_name = "");
|
||||||
~OffsetVfsFile() override;
|
~OffsetVfsFile() override;
|
||||||
|
|
||||||
std::string GetName() const override;
|
std::string GetName() const override;
|
||||||
|
@ -44,7 +44,6 @@ 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,6 +76,7 @@ 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};
|
||||||
|
@ -94,14 +95,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));
|
new RealVfsFile(*this, std::move(reference), path, perms, size, std::move(parent_path)));
|
||||||
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) {
|
||||||
|
@ -268,10 +269,11 @@ 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(FS::GetParentPath(path_)), path_components(FS::SplitPathComponentsCopy(path_)),
|
parent_path(parent_path_ ? std::move(*parent_path_) : FS::GetParentPath(path_)),
|
||||||
size(size_), perms(perms_) {}
|
path_components(FS::SplitPathComponentsCopy(path_)), size(size_), perms(perms_) {}
|
||||||
|
|
||||||
RealVfsFile::~RealVfsFile() {
|
RealVfsFile::~RealVfsFile() {
|
||||||
base.DropReference(std::move(reference));
|
base.DropReference(std::move(reference));
|
||||||
|
@ -348,7 +350,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(), perms));
|
out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), path, perms));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,6 +62,7 @@ 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:
|
||||||
|
@ -91,7 +92,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<u64> size = {}, std::optional<std::string> parent_path = {});
|
||||||
|
|
||||||
RealVfsFilesystem& base;
|
RealVfsFilesystem& base;
|
||||||
std::unique_ptr<FileReference> reference;
|
std::unique_ptr<FileReference> reference;
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#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"
|
||||||
|
@ -20,8 +19,8 @@
|
||||||
#include "core/hle/service/sm/sm.h"
|
#include "core/hle/service/sm/sm.h"
|
||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
namespace {
|
|
||||||
s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
|
static 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));
|
||||||
};
|
};
|
||||||
|
@ -50,7 +49,8 @@ s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) {
|
||||||
return epoch_s - 62135683200ll;
|
return epoch_s - 62135683200ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) {
|
static s64 GetEpochTimeFromInitialYear(
|
||||||
|
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,30 +65,31 @@ s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsSer
|
||||||
return CalendarTimeToEpoch(calendar);
|
return CalendarTimeToEpoch(calendar);
|
||||||
}
|
}
|
||||||
|
|
||||||
Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationName& in_name) {
|
static Service::PSC::Time::LocationName GetTimeZoneString(
|
||||||
|
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 (!IsTimeZoneBinaryValid(configured_name)) {
|
if (!time_zone_binary.IsValid(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(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!",
|
ASSERT_MSG(time_zone_binary.IsValid(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_worker{system, m_steady_clock_resource,
|
: m_steady_clock_resource{system}, m_time_zone_binary{system}, m_worker{
|
||||||
|
system,
|
||||||
|
m_steady_clock_resource,
|
||||||
m_file_timestamp_worker} {
|
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);
|
||||||
|
@ -99,7 +100,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 = MountTimeZoneBinary(system);
|
res = m_time_zone_binary.Mount();
|
||||||
ASSERT(res == ResultSuccess);
|
ASSERT(res == ResultSuccess);
|
||||||
|
|
||||||
m_worker.Initialize(m_time_sm, m_set_sys);
|
m_worker.Initialize(m_time_sm, m_set_sys);
|
||||||
|
@ -187,10 +188,6 @@ 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);
|
||||||
|
@ -236,7 +233,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(name);
|
auto configured_zone = GetTimeZoneString(m_time_zone_binary, name);
|
||||||
|
|
||||||
if (configured_zone != name) {
|
if (configured_zone != name) {
|
||||||
m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
|
m_set_sys->SetDeviceTimeZoneLocationName(configured_zone);
|
||||||
|
@ -254,13 +251,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 = GetTimeZoneCount();
|
auto location_count = m_time_zone_binary.GetTimeZoneCount();
|
||||||
Service::PSC::Time::RuleVersion rule_version{};
|
Service::PSC::Time::RuleVersion rule_version{};
|
||||||
GetTimeZoneVersion(rule_version);
|
m_time_zone_binary.GetTimeZoneVersion(rule_version);
|
||||||
|
|
||||||
std::span<const u8> rule_buffer{};
|
std::span<const u8> rule_buffer{};
|
||||||
size_t rule_size{};
|
size_t rule_size{};
|
||||||
res = GetTimeZoneRule(rule_buffer, rule_size, name);
|
res = m_time_zone_binary.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,6 +10,7 @@
|
||||||
#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"
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ namespace Service::Glue::Time {
|
||||||
class TimeManager {
|
class TimeManager {
|
||||||
public:
|
public:
|
||||||
explicit TimeManager(Core::System& system);
|
explicit TimeManager(Core::System& system);
|
||||||
~TimeManager();
|
~TimeManager() = default;
|
||||||
|
|
||||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ 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,8 +26,9 @@ 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_standard_steady_clock_resource{
|
m_file_timestamp_worker{time->m_file_timestamp_worker},
|
||||||
time->m_steady_clock_resource} {
|
m_standard_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"},
|
||||||
|
@ -106,7 +107,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);
|
m_time_zone_binary, m_time_zone);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,5 +80,6 @@ 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,19 +15,16 @@
|
||||||
#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,
|
bool can_write_timezone_device_location, TimeZoneBinary& time_zone_binary,
|
||||||
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_file_timestamp_worker{file_timestamp_worker}, m_wrapped_service{std::move(
|
||||||
m_wrapped_service{std::move(time_zone_service)}, m_operation_event{m_system} {
|
time_zone_service)},
|
||||||
|
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"},
|
||||||
|
@ -48,7 +45,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -69,13 +65,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(IsTimeZoneBinaryValid(location_name), Service::PSC::Time::ResultTimeZoneNotFound);
|
R_UNLESS(m_time_zone_binary.IsValid(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(GetTimeZoneRule(binary, binary_size, location_name))
|
R_TRY(m_time_zone_binary.GetTimeZoneRule(binary, binary_size, location_name))
|
||||||
|
|
||||||
R_TRY(m_wrapped_service->SetDeviceLocationNameWithTimeZoneRule(location_name, binary));
|
R_TRY(m_wrapped_service->SetDeviceLocationNameWithTimeZoneRule(location_name, binary));
|
||||||
|
|
||||||
|
@ -88,8 +84,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{g_list_mutex};
|
std::scoped_lock m{m_list_mutex};
|
||||||
for (auto& operation_event : g_list_nodes) {
|
for (auto& operation_event : m_list_nodes) {
|
||||||
operation_event.m_event->Signal();
|
operation_event.m_event->Signal();
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
@ -112,7 +108,8 @@ Result TimeZoneService::LoadLocationNameList(
|
||||||
};
|
};
|
||||||
|
|
||||||
std::scoped_lock l{m_mutex};
|
std::scoped_lock l{m_mutex};
|
||||||
R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index));
|
R_RETURN(
|
||||||
|
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,
|
||||||
|
@ -122,7 +119,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(GetTimeZoneRule(binary, binary_size, name))
|
R_TRY(m_time_zone_binary.GetTimeZoneRule(binary, binary_size, name))
|
||||||
R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
|
R_RETURN(m_wrapped_service->ParseTimeZoneBinary(out_rule, binary));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +171,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};
|
||||||
g_list_nodes.push_back(m_operation_event);
|
m_list_nodes.push_back(m_operation_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_event = &m_operation_event.m_event->GetReadableEvent();
|
*out_event = &m_operation_event.m_event->GetReadableEvent();
|
||||||
|
|
|
@ -32,6 +32,7 @@ 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>;
|
||||||
|
@ -40,7 +41,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,
|
bool can_write_timezone_device_location, TimeZoneBinary& time_zone_binary,
|
||||||
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service);
|
std::shared_ptr<Service::PSC::Time::TimeZoneService> time_zone_service);
|
||||||
|
|
||||||
~TimeZoneService() override;
|
~TimeZoneService() override;
|
||||||
|
@ -85,6 +86,10 @@ 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,18 +12,58 @@
|
||||||
#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;
|
||||||
|
|
||||||
static FileSys::VirtualDir g_time_zone_binary_romfs{};
|
void TimeZoneBinary::Reset() {
|
||||||
static Result g_time_zone_binary_mount_result{ResultUnknown};
|
time_zone_binary_romfs = {};
|
||||||
static std::vector<u8> g_time_zone_scratch_space(0x2800, 0);
|
time_zone_binary_mount_result = ResultUnknown;
|
||||||
|
time_zone_scratch_space.clear();
|
||||||
|
time_zone_scratch_space.resize(0x2800, 0);
|
||||||
|
}
|
||||||
|
|
||||||
Result TimeZoneReadBinary(size_t& out_read_size, std::span<u8> out_buffer, size_t out_buffer_size,
|
Result TimeZoneBinary::Mount() {
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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) {
|
std::string_view path) {
|
||||||
R_UNLESS(g_time_zone_binary_mount_result == ResultSuccess, g_time_zone_binary_mount_result);
|
R_UNLESS(time_zone_binary_mount_result == ResultSuccess, time_zone_binary_mount_result);
|
||||||
|
|
||||||
auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)};
|
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()};
|
||||||
|
@ -36,82 +76,37 @@ Result TimeZoneReadBinary(size_t& out_read_size, std::span<u8> out_buffer, size_
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void ResetTimeZoneBinary() {
|
void TimeZoneBinary::GetListPath(std::string& out_path) {
|
||||||
g_time_zone_binary_romfs = {};
|
if (time_zone_binary_mount_result != ResultSuccess) {
|
||||||
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 GetTimeZoneBinaryVersionPath(std::string& out_path) {
|
void TimeZoneBinary::GetVersionPath(std::string& out_path) {
|
||||||
if (g_time_zone_binary_mount_result != ResultSuccess) {
|
if (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 GetTimeZoneZonePath(std::string& out_path, const Service::PSC::Time::LocationName& name) {
|
void TimeZoneBinary::GetTimeZonePath(std::string& out_path,
|
||||||
if (g_time_zone_binary_mount_result != ResultSuccess) {
|
const Service::PSC::Time::LocationName& name) {
|
||||||
|
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 IsTimeZoneBinaryValid(const Service::PSC::Time::LocationName& name) {
|
bool TimeZoneBinary::IsValid(const Service::PSC::Time::LocationName& name) {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetTimeZoneZonePath(path, name);
|
GetTimeZonePath(path, name);
|
||||||
|
|
||||||
auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)};
|
auto vfs_file{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;
|
||||||
|
@ -119,19 +114,19 @@ bool IsTimeZoneBinaryValid(const Service::PSC::Time::LocationName& name) {
|
||||||
return vfs_file->GetSize() != 0;
|
return vfs_file->GetSize() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetTimeZoneCount() {
|
u32 TimeZoneBinary::GetTimeZoneCount() {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetTimeZoneBinaryListPath(path);
|
GetListPath(path);
|
||||||
|
|
||||||
size_t bytes_read{};
|
size_t bytes_read{};
|
||||||
if (TimeZoneReadBinary(bytes_read, g_time_zone_scratch_space, 0x2800, path) != ResultSuccess) {
|
if (Read(bytes_read, 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*>(g_time_zone_scratch_space.data()), bytes_read);
|
auto chars = std::span(reinterpret_cast<char*>(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') {
|
||||||
|
@ -141,50 +136,47 @@ u32 GetTimeZoneCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version) {
|
Result TimeZoneBinary::GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version) {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetTimeZoneBinaryVersionPath(path);
|
GetVersionPath(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(TimeZoneReadBinary(bytes_read, rule_version_buffer, rule_version_buffer.size_bytes(),
|
R_TRY(Read(bytes_read, rule_version_buffer, rule_version_buffer.size_bytes(), path));
|
||||||
path));
|
|
||||||
|
|
||||||
rule_version_buffer[bytes_read] = 0;
|
rule_version_buffer[bytes_read] = 0;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size,
|
Result TimeZoneBinary::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{};
|
||||||
GetTimeZoneZonePath(path, name);
|
GetTimeZonePath(path, name);
|
||||||
|
|
||||||
size_t bytes_read{};
|
size_t bytes_read{};
|
||||||
R_TRY(TimeZoneReadBinary(bytes_read, g_time_zone_scratch_space,
|
R_TRY(Read(bytes_read, time_zone_scratch_space, time_zone_scratch_space.size(), path));
|
||||||
g_time_zone_scratch_space.size(), path));
|
|
||||||
|
|
||||||
out_rule = std::span(g_time_zone_scratch_space.data(), bytes_read);
|
out_rule = std::span(time_zone_scratch_space.data(), bytes_read);
|
||||||
out_rule_size = bytes_read;
|
out_rule_size = bytes_read;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetTimeZoneLocationList(u32& out_count,
|
Result TimeZoneBinary::GetTimeZoneLocationList(
|
||||||
std::span<Service::PSC::Time::LocationName> out_names,
|
u32& out_count, std::span<Service::PSC::Time::LocationName> out_names, size_t max_names,
|
||||||
size_t max_names, u32 index) {
|
u32 index) {
|
||||||
std::string path{};
|
std::string path{};
|
||||||
GetTimeZoneBinaryListPath(path);
|
GetListPath(path);
|
||||||
|
|
||||||
size_t bytes_read{};
|
size_t bytes_read{};
|
||||||
R_TRY(TimeZoneReadBinary(bytes_read, g_time_zone_scratch_space,
|
R_TRY(Read(bytes_read, time_zone_scratch_space, time_zone_scratch_space.size(), path));
|
||||||
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{g_time_zone_scratch_space};
|
std::span<const u8> chars{time_zone_scratch_space};
|
||||||
u32 name_count{};
|
u32 name_count{};
|
||||||
|
|
||||||
for (auto chr : chars) {
|
for (auto chr : chars) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#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"
|
||||||
|
|
||||||
|
@ -15,12 +16,13 @@ class System;
|
||||||
|
|
||||||
namespace Service::Glue::Time {
|
namespace Service::Glue::Time {
|
||||||
|
|
||||||
void ResetTimeZoneBinary();
|
class TimeZoneBinary {
|
||||||
Result MountTimeZoneBinary(Core::System& system);
|
public:
|
||||||
void GetTimeZoneBinaryListPath(std::string& out_path);
|
explicit TimeZoneBinary(Core::System& system_)
|
||||||
void GetTimeZoneBinaryVersionPath(std::string& out_path);
|
: time_zone_scratch_space(0x2800, 0), system{system_} {}
|
||||||
void GetTimeZoneZonePath(std::string& out_path, const Service::PSC::Time::LocationName& name);
|
|
||||||
bool IsTimeZoneBinaryValid(const Service::PSC::Time::LocationName& name);
|
Result Mount();
|
||||||
|
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,
|
||||||
|
@ -29,4 +31,19 @@ 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,23 +16,6 @@
|
||||||
#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)
|
||||||
|
@ -43,11 +26,6 @@ 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,
|
||||||
|
@ -82,6 +60,14 @@ 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);
|
||||||
|
@ -91,8 +77,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 = GetSettingsItemValue<s32>(
|
auto steady_clock_interval_m =
|
||||||
m_set_sys, "time", "standard_steady_clock_rtc_update_interval_minutes");
|
GetSettingsItemValue<s32>("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()};
|
||||||
|
@ -102,8 +88,7 @@ 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 =
|
auto fs_notify_time_s = GetSettingsItemValue<s32>("time", "notify_time_to_fs_interval_seconds");
|
||||||
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};
|
||||||
|
@ -218,14 +203,14 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] auto offset_before{
|
[[maybe_unused]] auto offset_before{
|
||||||
g_ig_report_network_clock_context_set ? g_report_network_clock_context.offset : 0};
|
m_ig_report_network_clock_context_set ? m_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
|
||||||
g_report_network_clock_context = context;
|
m_report_network_clock_context = context;
|
||||||
if (!g_ig_report_network_clock_context_set) {
|
if (!m_ig_report_network_clock_context_set) {
|
||||||
g_ig_report_network_clock_context_set = true;
|
m_ig_report_network_clock_context_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_file_timestamp_worker.SetFilesystemPosixTime();
|
m_file_timestamp_worker.SetFilesystemPosixTime();
|
||||||
|
@ -247,16 +232,16 @@ void TimeWorker::ThreadFunc(std::stop_token stop_token) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] auto offset_before{g_ig_report_ephemeral_clock_context_set
|
[[maybe_unused]] auto offset_before{m_ig_report_ephemeral_clock_context_set
|
||||||
? g_report_ephemeral_clock_context.offset
|
? m_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
|
||||||
g_report_ephemeral_clock_context = context;
|
m_report_ephemeral_clock_context = context;
|
||||||
if (!g_ig_report_ephemeral_clock_context_set) {
|
if (!m_ig_report_ephemeral_clock_context_set) {
|
||||||
g_ig_report_ephemeral_clock_context_set = true;
|
m_ig_report_ephemeral_clock_context_set = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ 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;
|
||||||
|
@ -59,6 +62,11 @@ 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,13 +93,19 @@ ServerManager::~ServerManager() {
|
||||||
m_threads.clear();
|
m_threads.clear();
|
||||||
|
|
||||||
// Clean up ports.
|
// Clean up ports.
|
||||||
for (auto it = m_servers.begin(); it != m_servers.end(); it = m_servers.erase(it)) {
|
auto port_it = m_servers.begin();
|
||||||
delete std::addressof(*it);
|
while (port_it != m_servers.end()) {
|
||||||
|
auto* const port = std::addressof(*port_it);
|
||||||
|
port_it = m_servers.erase(port_it);
|
||||||
|
delete port;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up sessions.
|
// Clean up sessions.
|
||||||
for (auto it = m_sessions.begin(); it != m_sessions.end(); it = m_sessions.erase(it)) {
|
auto session_it = m_sessions.begin();
|
||||||
delete std::addressof(*it);
|
while (session_it != m_sessions.end()) {
|
||||||
|
auto* const session = std::addressof(*session_it);
|
||||||
|
session_it = m_sessions.erase(session_it);
|
||||||
|
delete session;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close wakeup event.
|
// Close wakeup event.
|
||||||
|
|
|
@ -36,22 +36,23 @@ std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FileType IdentifyFile(FileSys::VirtualFile file) {
|
FileType IdentifyFile(FileSys::VirtualFile file) {
|
||||||
if (const auto romdir_type = IdentifyFileLoader<AppLoader_DeconstructedRomDirectory>(file)) {
|
if (const auto nsp_type = IdentifyFileLoader<AppLoader_NSP>(file)) {
|
||||||
return *romdir_type;
|
return *nsp_type;
|
||||||
} else if (const auto nso_type = IdentifyFileLoader<AppLoader_NSO>(file)) {
|
} else if (const auto xci_type = IdentifyFileLoader<AppLoader_XCI>(file)) {
|
||||||
return *nso_type;
|
return *xci_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) {
|
||||||
const char format[] = "{} {} {}: {}";
|
constexpr std::string_view 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);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,12 @@ constexpr std::array DEPTH24_UNORM_STENCIL8_UINT{
|
||||||
VK_FORMAT_UNDEFINED,
|
VK_FORMAT_UNDEFINED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr std::array DEPTH24_UNORM_DONTCARE8{
|
||||||
|
VK_FORMAT_D32_SFLOAT,
|
||||||
|
VK_FORMAT_D16_UNORM,
|
||||||
|
VK_FORMAT_UNDEFINED,
|
||||||
|
};
|
||||||
|
|
||||||
constexpr std::array DEPTH16_UNORM_STENCIL8_UINT{
|
constexpr std::array DEPTH16_UNORM_STENCIL8_UINT{
|
||||||
VK_FORMAT_D24_UNORM_S8_UINT,
|
VK_FORMAT_D24_UNORM_S8_UINT,
|
||||||
VK_FORMAT_D32_SFLOAT_S8_UINT,
|
VK_FORMAT_D32_SFLOAT_S8_UINT,
|
||||||
|
@ -95,6 +101,8 @@ constexpr const VkFormat* GetFormatAlternatives(VkFormat format) {
|
||||||
return Alternatives::STENCIL8_UINT.data();
|
return Alternatives::STENCIL8_UINT.data();
|
||||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||||
return Alternatives::DEPTH24_UNORM_STENCIL8_UINT.data();
|
return Alternatives::DEPTH24_UNORM_STENCIL8_UINT.data();
|
||||||
|
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||||
|
return Alternatives::DEPTH24_UNORM_DONTCARE8.data();
|
||||||
case VK_FORMAT_D16_UNORM_S8_UINT:
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||||
return Alternatives::DEPTH16_UNORM_STENCIL8_UINT.data();
|
return Alternatives::DEPTH16_UNORM_STENCIL8_UINT.data();
|
||||||
case VK_FORMAT_B5G6R5_UNORM_PACK16:
|
case VK_FORMAT_B5G6R5_UNORM_PACK16:
|
||||||
|
|
Loading…
Reference in a new issue