summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt12
-rw-r--r--src/core/arm/arm_interface.cpp84
-rw-r--r--src/core/arm/arm_interface.h37
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h29
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp64
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h16
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp64
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h18
-rw-r--r--src/core/arm/dynarmic/dynarmic_cp15.cpp (renamed from src/core/arm/dynarmic/arm_dynarmic_cp15.cpp)2
-rw-r--r--src/core/arm/dynarmic/dynarmic_cp15.h (renamed from src/core/arm/dynarmic/arm_dynarmic_cp15.h)0
-rw-r--r--src/core/arm/dynarmic/dynarmic_exclusive_monitor.cpp (renamed from src/core/arm/dynarmic/arm_exclusive_monitor.cpp)2
-rw-r--r--src/core/arm/dynarmic/dynarmic_exclusive_monitor.h (renamed from src/core/arm/dynarmic/arm_exclusive_monitor.h)0
-rw-r--r--src/core/arm/exclusive_monitor.cpp2
-rw-r--r--src/core/core.cpp26
-rw-r--r--src/core/core.h8
-rw-r--r--src/core/core_timing.cpp52
-rw-r--r--src/core/core_timing.h14
-rw-r--r--src/core/core_timing_util.h58
-rw-r--r--src/core/file_sys/patch_manager.cpp9
-rw-r--r--src/core/file_sys/submission_package.h1
-rw-r--r--src/core/file_sys/system_archive/time_zone_binary.cpp706
-rw-r--r--src/core/file_sys/vfs_concat.cpp14
-rw-r--r--src/core/file_sys/vfs_real.cpp232
-rw-r--r--src/core/file_sys/vfs_real.h44
-rw-r--r--src/core/hid/emulated_controller.cpp93
-rw-r--r--src/core/hid/emulated_controller.h28
-rw-r--r--src/core/hid/input_converter.cpp6
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp5
-rw-r--r--src/core/hle/kernel/k_synchronization_object.cpp3
-rw-r--r--src/core/hle/kernel/k_thread.cpp23
-rw-r--r--src/core/hle/kernel/k_thread.h7
-rw-r--r--src/core/hle/kernel/svc/svc_info.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp7
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp10
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_tick.cpp10
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp2
-rw-r--r--src/core/hle/service/audio/audin_u.cpp16
-rw-r--r--src/core/hle/service/audio/audout_u.cpp15
-rw-r--r--src/core/hle/service/audio/audren_u.cpp22
-rw-r--r--src/core/hle/service/audio/audren_u.h1
-rw-r--r--src/core/hle/service/audio/hwopus.cpp9
-rw-r--r--src/core/hle/service/hid/hidbus.cpp1
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.cpp44
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.h9
-rw-r--r--src/core/hle/service/nfc/common/device.cpp270
-rw-r--r--src/core/hle/service/nfc/common/device.h21
-rw-r--r--src/core/hle/service/nfc/common/device_manager.cpp15
-rw-r--r--src/core/hle/service/nfc/common/device_manager.h2
-rw-r--r--src/core/hle/service/nfc/mifare_result.h2
-rw-r--r--src/core/hle/service/nfc/mifare_types.h11
-rw-r--r--src/core/hle/service/nfc/nfc_interface.cpp20
-rw-r--r--src/core/hle/service/nfc/nfc_result.h3
-rw-r--r--src/core/hle/service/nfc/nfc_types.h37
-rw-r--r--src/core/hle/service/nfp/nfp_types.h26
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdevice.h6
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp31
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h30
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp19
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h21
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp32
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h38
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp59
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h36
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp6
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp15
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h12
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h10
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp6
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp20
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h20
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp8
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h8
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.cpp24
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.h3
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp15
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h3
-rw-r--r--src/core/hle/service/nvnflinger/parcel.h7
-rw-r--r--src/core/hle/service/server_manager.cpp7
-rw-r--r--src/core/hle/service/server_manager.h4
-rw-r--r--src/core/hle/service/time/clock_types.h13
-rw-r--r--src/core/hle/service/time/standard_steady_clock_core.cpp2
-rw-r--r--src/core/hle/service/time/tick_based_steady_clock_core.cpp2
-rw-r--r--src/core/hle/service/time/time.cpp4
-rw-r--r--src/core/hle/service/time/time_manager.cpp34
-rw-r--r--src/core/hle/service/time/time_manager.h4
-rw-r--r--src/core/hle/service/time/time_sharedmemory.cpp5
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp26
-rw-r--r--src/core/hle/service/time/time_zone_manager.cpp161
-rw-r--r--src/core/hle/service/time/time_zone_manager.h8
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp67
-rw-r--r--src/core/hle/service/time/time_zone_service.h3
97 files changed, 1396 insertions, 1631 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 99602699a..3655b8478 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -4,8 +4,6 @@
add_library(core STATIC
arm/arm_interface.h
arm/arm_interface.cpp
- arm/dynarmic/arm_exclusive_monitor.cpp
- arm/dynarmic/arm_exclusive_monitor.h
arm/exclusive_monitor.cpp
arm/exclusive_monitor.h
arm/symbols.cpp
@@ -16,7 +14,6 @@ add_library(core STATIC
core.h
core_timing.cpp
core_timing.h
- core_timing_util.h
cpu_manager.cpp
cpu_manager.h
crypto/aes_util.cpp
@@ -836,7 +833,7 @@ endif()
create_target_directory_groups(core)
-target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core)
+target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core nx_tzdb)
target_link_libraries(core PUBLIC Boost::headers PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::opus)
if (MINGW)
target_link_libraries(core PRIVATE ${MSWSOCK_LIBRARY})
@@ -849,12 +846,15 @@ endif()
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
target_sources(core PRIVATE
+ arm/dynarmic/arm_dynarmic.h
arm/dynarmic/arm_dynarmic_64.cpp
arm/dynarmic/arm_dynarmic_64.h
arm/dynarmic/arm_dynarmic_32.cpp
arm/dynarmic/arm_dynarmic_32.h
- arm/dynarmic/arm_dynarmic_cp15.cpp
- arm/dynarmic/arm_dynarmic_cp15.h
+ arm/dynarmic/dynarmic_cp15.cpp
+ arm/dynarmic/dynarmic_cp15.h
+ arm/dynarmic/dynarmic_exclusive_monitor.cpp
+ arm/dynarmic/dynarmic_exclusive_monitor.h
hle/service/jit/jit_context.cpp
hle/service/jit/jit_context.h
hle/service/jit/jit.cpp
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index d30914b7a..beaea64b3 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -13,25 +13,68 @@
#include "core/core.h"
#include "core/debugger/debugger.h"
#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/svc.h"
#include "core/loader/loader.h"
#include "core/memory.h"
-#include "core/arm/dynarmic/arm_dynarmic_32.h"
-#include "core/arm/dynarmic/arm_dynarmic_64.h"
-
namespace Core {
constexpr u64 SEGMENT_BASE = 0x7100000000ull;
std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
Core::System& system, const ARM_Interface::ThreadContext32& ctx) {
- return ARM_Dynarmic_32::GetBacktraceFromContext(system, ctx);
+ std::vector<BacktraceEntry> out;
+ auto& memory = system.ApplicationMemory();
+
+ const auto& reg = ctx.cpu_registers;
+ u32 pc = reg[15], lr = reg[14], fp = reg[11];
+ out.push_back({"", 0, pc, 0, ""});
+
+ // fp (= r11) points to the last frame record.
+ // Frame records are two words long:
+ // fp+0 : pointer to previous frame record
+ // fp+4 : value of lr for frame
+ for (size_t i = 0; i < 256; i++) {
+ out.push_back({"", 0, lr, 0, ""});
+ if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) {
+ break;
+ }
+ lr = memory.Read32(fp + 4);
+ fp = memory.Read32(fp);
+ }
+
+ SymbolicateBacktrace(system, out);
+
+ return out;
}
std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext(
Core::System& system, const ARM_Interface::ThreadContext64& ctx) {
- return ARM_Dynarmic_64::GetBacktraceFromContext(system, ctx);
+ std::vector<BacktraceEntry> out;
+ auto& memory = system.ApplicationMemory();
+
+ const auto& reg = ctx.cpu_registers;
+ u64 pc = ctx.pc, lr = reg[30], fp = reg[29];
+
+ out.push_back({"", 0, pc, 0, ""});
+
+ // fp (= x29) points to the previous frame record.
+ // Frame records are two words long:
+ // fp+0 : pointer to previous frame record
+ // fp+8 : value of lr for frame
+ for (size_t i = 0; i < 256; i++) {
+ out.push_back({"", 0, lr, 0, ""});
+ if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) {
+ break;
+ }
+ lr = memory.Read64(fp + 8);
+ fp = memory.Read64(fp);
+ }
+
+ SymbolicateBacktrace(system, out);
+
+ return out;
}
void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out) {
@@ -76,6 +119,18 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt
}
}
+std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const {
+ if (GetArchitecture() == Architecture::Aarch64) {
+ ThreadContext64 ctx;
+ SaveContext(ctx);
+ return GetBacktraceFromContext(system, ctx);
+ } else {
+ ThreadContext32 ctx;
+ SaveContext(ctx);
+ return GetBacktraceFromContext(system, ctx);
+ }
+}
+
void ARM_Interface::LogBacktrace() const {
const VAddr sp = GetSP();
const VAddr pc = GetPC();
@@ -83,7 +138,6 @@ void ARM_Interface::LogBacktrace() const {
LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address",
"Offset", "Symbol");
LOG_ERROR(Core_ARM, "");
-
const auto backtrace = GetBacktrace();
for (const auto& entry : backtrace) {
LOG_ERROR(Core_ARM, "{:20}{:016X} {:016X} {:016X} {}", entry.module, entry.address,
@@ -97,7 +151,7 @@ void ARM_Interface::Run() {
while (true) {
Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())};
- Dynarmic::HaltReason hr{};
+ HaltReason hr{};
// Notify the debugger and go to sleep if a step was performed
// and this thread has been scheduled again.
@@ -108,17 +162,17 @@ void ARM_Interface::Run() {
}
// Otherwise, run the thread.
- system.EnterDynarmicProfile();
+ system.EnterCPUProfile();
if (current_thread->GetStepState() == StepState::StepPending) {
hr = StepJit();
- if (Has(hr, step_thread)) {
+ if (True(hr & HaltReason::StepThread)) {
current_thread->SetStepState(StepState::StepPerformed);
}
} else {
hr = RunJit();
}
- system.ExitDynarmicProfile();
+ system.ExitCPUProfile();
// If the thread is scheduled for termination, exit the thread.
if (current_thread->HasDpc()) {
@@ -130,8 +184,8 @@ void ARM_Interface::Run() {
// Notify the debugger and go to sleep if a breakpoint was hit,
// or if the thread is unable to continue for any reason.
- if (Has(hr, breakpoint) || Has(hr, no_execute)) {
- if (!Has(hr, no_execute)) {
+ if (True(hr & HaltReason::InstructionBreakpoint) || True(hr & HaltReason::PrefetchAbort)) {
+ if (!True(hr & HaltReason::InstructionBreakpoint)) {
RewindBreakpointInstruction();
}
if (system.DebuggerEnabled()) {
@@ -144,7 +198,7 @@ void ARM_Interface::Run() {
}
// Notify the debugger and go to sleep if a watchpoint was hit.
- if (Has(hr, watchpoint)) {
+ if (True(hr & HaltReason::DataAbort)) {
if (system.DebuggerEnabled()) {
system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint());
}
@@ -153,11 +207,11 @@ void ARM_Interface::Run() {
}
// Handle syscalls and scheduling (this may change the current thread/core)
- if (Has(hr, svc_call)) {
+ if (True(hr & HaltReason::SupervisorCall)) {
Kernel::Svc::Call(system, GetSvcNumber());
break;
}
- if (Has(hr, break_loop) || !uses_wall_clock) {
+ if (True(hr & HaltReason::BreakLoop) || !uses_wall_clock) {
break;
}
}
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 8e40702cc..d5f2fa09a 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -8,8 +8,6 @@
#include <string>
#include <vector>
-#include <dynarmic/interface/halt_reason.h>
-
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/hardware_properties.h"
@@ -30,6 +28,22 @@ class CPUInterruptHandler;
using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>;
+// NOTE: these values match the HaltReason enum in Dynarmic
+enum class HaltReason : u64 {
+ StepThread = 0x00000001,
+ DataAbort = 0x00000004,
+ BreakLoop = 0x02000000,
+ SupervisorCall = 0x04000000,
+ InstructionBreakpoint = 0x08000000,
+ PrefetchAbort = 0x20000000,
+};
+DECLARE_ENUM_FLAG_OPERATORS(HaltReason);
+
+enum class Architecture {
+ Aarch32,
+ Aarch64,
+};
+
/// Generic ARMv8 CPU interface
class ARM_Interface {
public:
@@ -167,8 +181,9 @@ public:
*/
virtual void SetTPIDR_EL0(u64 value) = 0;
- virtual void SaveContext(ThreadContext32& ctx) = 0;
- virtual void SaveContext(ThreadContext64& ctx) = 0;
+ virtual Architecture GetArchitecture() const = 0;
+ virtual void SaveContext(ThreadContext32& ctx) const = 0;
+ virtual void SaveContext(ThreadContext64& ctx) const = 0;
virtual void LoadContext(const ThreadContext32& ctx) = 0;
virtual void LoadContext(const ThreadContext64& ctx) = 0;
void LoadWatchpointArray(const WatchpointArray& wp);
@@ -195,17 +210,9 @@ public:
static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
const ThreadContext64& ctx);
- virtual std::vector<BacktraceEntry> GetBacktrace() const = 0;
-
+ std::vector<BacktraceEntry> GetBacktrace() const;
void LogBacktrace() const;
- static constexpr Dynarmic::HaltReason step_thread = Dynarmic::HaltReason::Step;
- static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
- static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
- static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
- static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::MemoryAbort;
- static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6;
-
protected:
/// System context that this ARM interface is running under.
System& system;
@@ -216,8 +223,8 @@ protected:
const Kernel::DebugWatchpoint* MatchingWatchpoint(
u64 addr, u64 size, Kernel::DebugWatchpointType access_type) const;
- virtual Dynarmic::HaltReason RunJit() = 0;
- virtual Dynarmic::HaltReason StepJit() = 0;
+ virtual HaltReason RunJit() = 0;
+ virtual HaltReason StepJit() = 0;
virtual u32 GetSvcNumber() const = 0;
virtual const Kernel::DebugWatchpoint* HaltedWatchpoint() const = 0;
virtual void RewindBreakpointInstruction() = 0;
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
new file mode 100644
index 000000000..eef7c3116
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -0,0 +1,29 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <dynarmic/interface/halt_reason.h>
+
+#include "core/arm/arm_interface.h"
+
+namespace Core {
+
+constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step;
+constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort;
+constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2;
+constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3;
+constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4;
+constexpr Dynarmic::HaltReason PrefetchAbort = Dynarmic::HaltReason::UserDefined6;
+
+constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
+ static_assert(static_cast<u64>(HaltReason::StepThread) == static_cast<u64>(StepThread));
+ static_assert(static_cast<u64>(HaltReason::DataAbort) == static_cast<u64>(DataAbort));
+ static_assert(static_cast<u64>(HaltReason::BreakLoop) == static_cast<u64>(BreakLoop));
+ static_assert(static_cast<u64>(HaltReason::SupervisorCall) == static_cast<u64>(SupervisorCall));
+ static_assert(static_cast<u64>(HaltReason::InstructionBreakpoint) ==
+ static_cast<u64>(InstructionBreakpoint));
+ static_assert(static_cast<u64>(HaltReason::PrefetchAbort) == static_cast<u64>(PrefetchAbort));
+
+ return static_cast<HaltReason>(hr);
+}
+
+} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index dfdcbe35a..5acf9008d 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -10,9 +10,10 @@
#include "common/logging/log.h"
#include "common/page_table.h"
#include "common/settings.h"
+#include "core/arm/dynarmic/arm_dynarmic.h"
#include "core/arm/dynarmic/arm_dynarmic_32.h"
-#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
-#include "core/arm/dynarmic/arm_exclusive_monitor.h"
+#include "core/arm/dynarmic/dynarmic_cp15.h"
+#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/debugger/debugger.h"
@@ -104,11 +105,11 @@ public:
switch (exception) {
case Dynarmic::A32::Exception::NoExecuteFault:
LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#08x}", pc);
- ReturnException(pc, ARM_Interface::no_execute);
+ ReturnException(pc, PrefetchAbort);
return;
default:
if (debugger_enabled) {
- ReturnException(pc, ARM_Interface::breakpoint);
+ ReturnException(pc, InstructionBreakpoint);
return;
}
@@ -121,7 +122,7 @@ public:
void CallSVC(u32 swi) override {
parent.svc_swi = swi;
- parent.jit.load()->HaltExecution(ARM_Interface::svc_call);
+ parent.jit.load()->HaltExecution(SupervisorCall);
}
void AddTicks(u64 ticks) override {
@@ -162,7 +163,7 @@ public:
if (!memory.IsValidVirtualAddressRange(addr, size)) {
LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
addr);
- parent.jit.load()->HaltExecution(ARM_Interface::no_execute);
+ parent.jit.load()->HaltExecution(PrefetchAbort);
return false;
}
@@ -173,7 +174,7 @@ public:
const auto match{parent.MatchingWatchpoint(addr, size, type)};
if (match) {
parent.halted_watchpoint = match;
- parent.jit.load()->HaltExecution(ARM_Interface::watchpoint);
+ parent.jit.load()->HaltExecution(DataAbort);
return false;
}
@@ -329,12 +330,12 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
return std::make_unique<Dynarmic::A32::Jit>(config);
}
-Dynarmic::HaltReason ARM_Dynarmic_32::RunJit() {
- return jit.load()->Run();
+HaltReason ARM_Dynarmic_32::RunJit() {
+ return TranslateHaltReason(jit.load()->Run());
}
-Dynarmic::HaltReason ARM_Dynarmic_32::StepJit() {
- return jit.load()->Step();
+HaltReason ARM_Dynarmic_32::StepJit() {
+ return TranslateHaltReason(jit.load()->Step());
}
u32 ARM_Dynarmic_32::GetSvcNumber() const {
@@ -408,7 +409,7 @@ void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
cp15->uprw = static_cast<u32>(value);
}
-void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
+void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) const {
Dynarmic::A32::Jit* j = jit.load();
ctx.cpu_registers = j->Regs();
ctx.extension_registers = j->ExtRegs();
@@ -425,11 +426,11 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
}
void ARM_Dynarmic_32::SignalInterrupt() {
- jit.load()->HaltExecution(break_loop);
+ jit.load()->HaltExecution(BreakLoop);
}
void ARM_Dynarmic_32::ClearInterrupt() {
- jit.load()->ClearHalt(break_loop);
+ jit.load()->ClearHalt(BreakLoop);
}
void ARM_Dynarmic_32::ClearInstructionCache() {
@@ -462,39 +463,4 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
jit_cache.emplace(key, std::move(new_jit));
}
-std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system,
- u64 fp, u64 lr, u64 pc) {
- std::vector<BacktraceEntry> out;
- auto& memory = system.ApplicationMemory();
-
- out.push_back({"", 0, pc, 0, ""});
-
- // fp (= r11) points to the last frame record.
- // Frame records are two words long:
- // fp+0 : pointer to previous frame record
- // fp+4 : value of lr for frame
- for (size_t i = 0; i < 256; i++) {
- out.push_back({"", 0, lr, 0, ""});
- if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) {
- break;
- }
- lr = memory.Read32(fp + 4);
- fp = memory.Read32(fp);
- }
-
- SymbolicateBacktrace(system, out);
-
- return out;
-}
-
-std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext(
- System& system, const ThreadContext32& ctx) {
- const auto& reg = ctx.cpu_registers;
- return GetBacktrace(system, reg[11], reg[14], reg[15]);
-}
-
-std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const {
- return GetBacktrace(system, GetReg(11), GetReg(14), GetReg(15));
-}
-
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index bce695daf..a990845cb 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -50,8 +50,11 @@ public:
return (GetPSTATE() & 0x20) != 0;
}
- void SaveContext(ThreadContext32& ctx) override;
- void SaveContext(ThreadContext64& ctx) override {}
+ Architecture GetArchitecture() const override {
+ return Architecture::Aarch32;
+ }
+ void SaveContext(ThreadContext32& ctx) const override;
+ void SaveContext(ThreadContext64& ctx) const override {}
void LoadContext(const ThreadContext32& ctx) override;
void LoadContext(const ThreadContext64& ctx) override {}
@@ -64,14 +67,9 @@ public:
void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override;
- static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
- const ThreadContext32& ctx);
-
- std::vector<BacktraceEntry> GetBacktrace() const override;
-
protected:
- Dynarmic::HaltReason RunJit() override;
- Dynarmic::HaltReason StepJit() override;
+ HaltReason RunJit() override;
+ HaltReason StepJit() override;
u32 GetSvcNumber() const override;
const Kernel::DebugWatchpoint* HaltedWatchpoint() const override;
void RewindBreakpointInstruction() override;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index bbbcb4f9d..bb97ed5bc 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -10,8 +10,9 @@
#include "common/logging/log.h"
#include "common/page_table.h"
#include "common/settings.h"
+#include "core/arm/dynarmic/arm_dynarmic.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h"
-#include "core/arm/dynarmic/arm_exclusive_monitor.h"
+#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/debugger/debugger.h"
@@ -113,7 +114,7 @@ public:
LOG_ERROR(Core_ARM,
"Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
num_instructions, memory.Read32(pc));
- ReturnException(pc, ARM_Interface::no_execute);
+ ReturnException(pc, PrefetchAbort);
}
void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op,
@@ -148,11 +149,11 @@ public:
return;
case Dynarmic::A64::Exception::NoExecuteFault:
LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#016x}", pc);
- ReturnException(pc, ARM_Interface::no_execute);
+ ReturnException(pc, PrefetchAbort);
return;
default:
if (debugger_enabled) {
- ReturnException(pc, ARM_Interface::breakpoint);
+ ReturnException(pc, InstructionBreakpoint);
return;
}
@@ -164,7 +165,7 @@ public:
void CallSVC(u32 swi) override {
parent.svc_swi = swi;
- parent.jit.load()->HaltExecution(ARM_Interface::svc_call);
+ parent.jit.load()->HaltExecution(SupervisorCall);
}
void AddTicks(u64 ticks) override {
@@ -207,7 +208,7 @@ public:
if (!memory.IsValidVirtualAddressRange(addr, size)) {
LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
addr);
- parent.jit.load()->HaltExecution(ARM_Interface::no_execute);
+ parent.jit.load()->HaltExecution(PrefetchAbort);
return false;
}
@@ -218,7 +219,7 @@ public:
const auto match{parent.MatchingWatchpoint(addr, size, type)};
if (match) {
parent.halted_watchpoint = match;
- parent.jit.load()->HaltExecution(ARM_Interface::watchpoint);
+ parent.jit.load()->HaltExecution(DataAbort);
return false;
}
@@ -383,12 +384,12 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
return std::make_shared<Dynarmic::A64::Jit>(config);
}
-Dynarmic::HaltReason ARM_Dynarmic_64::RunJit() {
- return jit.load()->Run();
+HaltReason ARM_Dynarmic_64::RunJit() {
+ return TranslateHaltReason(jit.load()->Run());
}
-Dynarmic::HaltReason ARM_Dynarmic_64::StepJit() {
- return jit.load()->Step();
+HaltReason ARM_Dynarmic_64::StepJit() {
+ return TranslateHaltReason(jit.load()->Step());
}
u32 ARM_Dynarmic_64::GetSvcNumber() const {
@@ -464,7 +465,7 @@ void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
cb->tpidr_el0 = value;
}
-void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
+void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) const {
Dynarmic::A64::Jit* j = jit.load();
ctx.cpu_registers = j->GetRegisters();
ctx.sp = j->GetSP();
@@ -489,11 +490,11 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
}
void ARM_Dynarmic_64::SignalInterrupt() {
- jit.load()->HaltExecution(break_loop);
+ jit.load()->HaltExecution(BreakLoop);
}
void ARM_Dynarmic_64::ClearInterrupt() {
- jit.load()->ClearHalt(break_loop);
+ jit.load()->ClearHalt(BreakLoop);
}
void ARM_Dynarmic_64::ClearInstructionCache() {
@@ -526,39 +527,4 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
jit_cache.emplace(key, std::move(new_jit));
}
-std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system,
- u64 fp, u64 lr, u64 pc) {
- std::vector<BacktraceEntry> out;
- auto& memory = system.ApplicationMemory();
-
- out.push_back({"", 0, pc, 0, ""});
-
- // fp (= x29) points to the previous frame record.
- // Frame records are two words long:
- // fp+0 : pointer to previous frame record
- // fp+8 : value of lr for frame
- for (size_t i = 0; i < 256; i++) {
- out.push_back({"", 0, lr, 0, ""});
- if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) {
- break;
- }
- lr = memory.Read64(fp + 8);
- fp = memory.Read64(fp);
- }
-
- SymbolicateBacktrace(system, out);
-
- return out;
-}
-
-std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext(
- System& system, const ThreadContext64& ctx) {
- const auto& reg = ctx.cpu_registers;
- return GetBacktrace(system, reg[29], reg[30], ctx.pc);
-}
-
-std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const {
- return GetBacktrace(system, GetReg(29), GetReg(30), GetPC());
-}
-
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index e83599e82..af2aa1f1c 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -43,8 +43,11 @@ public:
void SetTPIDR_EL0(u64 value) override;
u64 GetTPIDR_EL0() const override;
- void SaveContext(ThreadContext32& ctx) override {}
- void SaveContext(ThreadContext64& ctx) override;
+ Architecture GetArchitecture() const override {
+ return Architecture::Aarch64;
+ }
+ void SaveContext(ThreadContext32& ctx) const override {}
+ void SaveContext(ThreadContext64& ctx) const override;
void LoadContext(const ThreadContext32& ctx) override {}
void LoadContext(const ThreadContext64& ctx) override;
@@ -57,14 +60,9 @@ public:
void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override;
- static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system,
- const ThreadContext64& ctx);
-
- std::vector<BacktraceEntry> GetBacktrace() const override;
-
protected:
- Dynarmic::HaltReason RunJit() override;
- Dynarmic::HaltReason StepJit() override;
+ HaltReason RunJit() override;
+ HaltReason StepJit() override;
u32 GetSvcNumber() const override;
const Kernel::DebugWatchpoint* HaltedWatchpoint() const override;
void RewindBreakpointInstruction() override;
@@ -73,8 +71,6 @@ private:
std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table,
std::size_t address_space_bits) const;
- static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr, u64 pc);
-
using JitCacheKey = std::pair<Common::PageTable*, std::size_t>;
using JitCacheType =
std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/dynarmic_cp15.cpp
index 5a4eba3eb..92c548db0 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
+++ b/src/core/arm/dynarmic/dynarmic_cp15.cpp
@@ -4,7 +4,7 @@
#include <fmt/format.h>
#include "common/logging/log.h"
#include "core/arm/dynarmic/arm_dynarmic_32.h"
-#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
+#include "core/arm/dynarmic/dynarmic_cp15.h"
#include "core/core.h"
#include "core/core_timing.h"
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/dynarmic_cp15.h
index d90b3e568..d90b3e568 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h
+++ b/src/core/arm/dynarmic/dynarmic_cp15.h
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.cpp b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.cpp
index fa0c48b25..b5c9c43c4 100644
--- a/src/core/arm/dynarmic/arm_exclusive_monitor.cpp
+++ b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.cpp
@@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include "core/arm/dynarmic/arm_exclusive_monitor.h"
+#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
#include "core/memory.h"
namespace Core {
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.h b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
index 57e6dd0d0..57e6dd0d0 100644
--- a/src/core/arm/dynarmic/arm_exclusive_monitor.h
+++ b/src/core/arm/dynarmic/dynarmic_exclusive_monitor.h
diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp
index 20550faeb..6d9a862e1 100644
--- a/src/core/arm/exclusive_monitor.cpp
+++ b/src/core/arm/exclusive_monitor.cpp
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
-#include "core/arm/dynarmic/arm_exclusive_monitor.h"
+#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
#endif
#include "core/arm/exclusive_monitor.h"
#include "core/memory.h"
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 7ba704f18..b74fd0a58 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -54,10 +54,10 @@
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
-MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU0, "ARM JIT", "Dynarmic CPU 0", MP_RGB(255, 64, 64));
-MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU1, "ARM JIT", "Dynarmic CPU 1", MP_RGB(255, 64, 64));
-MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU2, "ARM JIT", "Dynarmic CPU 2", MP_RGB(255, 64, 64));
-MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU3, "ARM JIT", "Dynarmic CPU 3", MP_RGB(255, 64, 64));
+MICROPROFILE_DEFINE(ARM_CPU0, "ARM", "CPU 0", MP_RGB(255, 64, 64));
+MICROPROFILE_DEFINE(ARM_CPU1, "ARM", "CPU 1", MP_RGB(255, 64, 64));
+MICROPROFILE_DEFINE(ARM_CPU2, "ARM", "CPU 2", MP_RGB(255, 64, 64));
+MICROPROFILE_DEFINE(ARM_CPU3, "ARM", "CPU 3", MP_RGB(255, 64, 64));
namespace Core {
@@ -259,10 +259,10 @@ struct System::Impl {
is_powered_on = true;
exit_lock = false;
- microprofile_dynarmic[0] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU0);
- microprofile_dynarmic[1] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU1);
- microprofile_dynarmic[2] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU2);
- microprofile_dynarmic[3] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU3);
+ microprofile_cpu[0] = MICROPROFILE_TOKEN(ARM_CPU0);
+ microprofile_cpu[1] = MICROPROFILE_TOKEN(ARM_CPU1);
+ microprofile_cpu[2] = MICROPROFILE_TOKEN(ARM_CPU2);
+ microprofile_cpu[3] = MICROPROFILE_TOKEN(ARM_CPU3);
LOG_DEBUG(Core, "Initialized OK");
@@ -539,7 +539,7 @@ struct System::Impl {
ExitCallback exit_callback;
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
- std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{};
+ std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
};
System::System() : impl{std::make_unique<Impl>(*this)} {}
@@ -927,14 +927,14 @@ void System::RegisterHostThread() {
impl->kernel.RegisterHostThread();
}
-void System::EnterDynarmicProfile() {
+void System::EnterCPUProfile() {
std::size_t core = impl->kernel.GetCurrentHostThreadID();
- impl->dynarmic_ticks[core] = MicroProfileEnter(impl->microprofile_dynarmic[core]);
+ impl->dynarmic_ticks[core] = MicroProfileEnter(impl->microprofile_cpu[core]);
}
-void System::ExitDynarmicProfile() {
+void System::ExitCPUProfile() {
std::size_t core = impl->kernel.GetCurrentHostThreadID();
- MicroProfileLeave(impl->microprofile_dynarmic[core], impl->dynarmic_ticks[core]);
+ MicroProfileLeave(impl->microprofile_cpu[core], impl->dynarmic_ticks[core]);
}
bool System::IsMulticore() const {
diff --git a/src/core/core.h b/src/core/core.h
index ff2e4bd30..93afc9303 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -412,11 +412,11 @@ public:
/// Register a host thread as an auxiliary thread.
void RegisterHostThread();
- /// Enter Dynarmic Microprofile
- void EnterDynarmicProfile();
+ /// Enter CPU Microprofile
+ void EnterCPUProfile();
- /// Exit Dynarmic Microprofile
- void ExitDynarmicProfile();
+ /// Exit CPU Microprofile
+ void ExitCPUProfile();
/// Tells if system is running on multicore.
[[nodiscard]] bool IsMulticore() const;
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 4f2692b05..4f0a3f8ea 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -16,12 +16,11 @@
#include "common/microprofile.h"
#include "core/core_timing.h"
-#include "core/core_timing_util.h"
#include "core/hardware_properties.h"
namespace Core::Timing {
-constexpr s64 MAX_SLICE_LENGTH = 4000;
+constexpr s64 MAX_SLICE_LENGTH = 10000;
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
return std::make_shared<EventType>(std::move(callback), std::move(name));
@@ -45,9 +44,7 @@ struct CoreTiming::Event {
}
};
-CoreTiming::CoreTiming()
- : cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)},
- event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
+CoreTiming::CoreTiming() : clock{Common::CreateOptimalClock()} {}
CoreTiming::~CoreTiming() {
Reset();
@@ -68,7 +65,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
on_thread_init = std::move(on_thread_init_);
event_fifo_id = 0;
shutting_down = false;
- ticks = 0;
+ cpu_ticks = 0;
const auto empty_timed_callback = [](std::uintptr_t, u64, std::chrono::nanoseconds)
-> std::optional<std::chrono::nanoseconds> { return std::nullopt; };
ev_lost = CreateEvent("_lost_event", empty_timed_callback);
@@ -173,38 +170,30 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
}
void CoreTiming::AddTicks(u64 ticks_to_add) {
- ticks += ticks_to_add;
- downcount -= static_cast<s64>(ticks);
+ cpu_ticks += ticks_to_add;
+ downcount -= static_cast<s64>(cpu_ticks);
}
void CoreTiming::Idle() {
- if (!event_queue.empty()) {
- const u64 next_event_time = event_queue.front().time;
- const u64 next_ticks = nsToCycles(std::chrono::nanoseconds(next_event_time)) + 10U;
- if (next_ticks > ticks) {
- ticks = next_ticks;
- }
- return;
- }
- ticks += 1000U;
+ cpu_ticks += 1000U;
}
void CoreTiming::ResetTicks() {
downcount = MAX_SLICE_LENGTH;
}
-u64 CoreTiming::GetCPUTicks() const {
+u64 CoreTiming::GetClockTicks() const {
if (is_multicore) [[likely]] {
- return cpu_clock->GetCPUCycles();
+ return clock->GetCNTPCT();
}
- return ticks;
+ return Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
}
-u64 CoreTiming::GetClockTicks() const {
+u64 CoreTiming::GetGPUTicks() const {
if (is_multicore) [[likely]] {
- return cpu_clock->GetClockCycles();
+ return clock->GetGPUTick();
}
- return CpuCyclesToClockCycles(ticks);
+ return Common::WallClock::CPUTickToGPUTick(cpu_ticks);
}
std::optional<s64> CoreTiming::Advance() {
@@ -297,9 +286,7 @@ void CoreTiming::ThreadLoop() {
}
paused_set = true;
- event_clock->Pause(true);
pause_event.Wait();
- event_clock->Pause(false);
}
}
@@ -315,25 +302,18 @@ void CoreTiming::Reset() {
has_started = false;
}
-std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const {
- if (is_multicore) [[likely]] {
- return cpu_clock->GetTimeNS();
- }
- return CyclesToNs(ticks);
-}
-
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
if (is_multicore) [[likely]] {
- return event_clock->GetTimeNS();
+ return clock->GetTimeNS();
}
- return CyclesToNs(ticks);
+ return std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
}
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
if (is_multicore) [[likely]] {
- return event_clock->GetTimeUS();
+ return clock->GetTimeUS();
}
- return CyclesToUs(ticks);
+ return std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
}
} // namespace Core::Timing
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index e7c4a949f..10db1de55 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -116,14 +116,11 @@ public:
return downcount;
}
- /// Returns current time in emulated CPU cycles
- u64 GetCPUTicks() const;
-
- /// Returns current time in emulated in Clock cycles
+ /// Returns the current CNTPCT tick value.
u64 GetClockTicks() const;
- /// Returns current time in nanoseconds.
- std::chrono::nanoseconds GetCPUTimeNs() const;
+ /// Returns the current GPU tick value.
+ u64 GetGPUTicks() const;
/// Returns current time in microseconds.
std::chrono::microseconds GetGlobalTimeUs() const;
@@ -142,8 +139,7 @@ private:
void Reset();
- std::unique_ptr<Common::WallClock> cpu_clock;
- std::unique_ptr<Common::WallClock> event_clock;
+ std::unique_ptr<Common::WallClock> clock;
s64 global_timer = 0;
@@ -171,7 +167,7 @@ private:
s64 pause_end_time{};
/// Cycle timing
- u64 ticks{};
+ u64 cpu_ticks{};
s64 downcount{};
};
diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h
deleted file mode 100644
index fe5aaefc7..000000000
--- a/src/core/core_timing_util.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include <chrono>
-
-#include "common/common_types.h"
-#include "core/hardware_properties.h"
-
-namespace Core::Timing {
-
-namespace detail {
-constexpr u64 CNTFREQ_ADJUSTED = Hardware::CNTFREQ / 1000;
-constexpr u64 BASE_CLOCK_RATE_ADJUSTED = Hardware::BASE_CLOCK_RATE / 1000;
-} // namespace detail
-
-[[nodiscard]] constexpr s64 msToCycles(std::chrono::milliseconds ms) {
- return ms.count() * detail::BASE_CLOCK_RATE_ADJUSTED;
-}
-
-[[nodiscard]] constexpr s64 usToCycles(std::chrono::microseconds us) {
- return us.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000;
-}
-
-[[nodiscard]] constexpr s64 nsToCycles(std::chrono::nanoseconds ns) {
- return ns.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000000;
-}
-
-[[nodiscard]] constexpr u64 msToClockCycles(std::chrono::milliseconds ms) {
- return static_cast<u64>(ms.count()) * detail::CNTFREQ_ADJUSTED;
-}
-
-[[nodiscard]] constexpr u64 usToClockCycles(std::chrono::microseconds us) {
- return us.count() * detail::CNTFREQ_ADJUSTED / 1000;
-}
-
-[[nodiscard]] constexpr u64 nsToClockCycles(std::chrono::nanoseconds ns) {
- return ns.count() * detail::CNTFREQ_ADJUSTED / 1000000;
-}
-
-[[nodiscard]] constexpr u64 CpuCyclesToClockCycles(u64 ticks) {
- return ticks * detail::CNTFREQ_ADJUSTED / detail::BASE_CLOCK_RATE_ADJUSTED;
-}
-
-[[nodiscard]] constexpr std::chrono::milliseconds CyclesToMs(s64 cycles) {
- return std::chrono::milliseconds(cycles / detail::BASE_CLOCK_RATE_ADJUSTED);
-}
-
-[[nodiscard]] constexpr std::chrono::nanoseconds CyclesToNs(s64 cycles) {
- return std::chrono::nanoseconds(cycles * 1000000 / detail::BASE_CLOCK_RATE_ADJUSTED);
-}
-
-[[nodiscard]] constexpr std::chrono::microseconds CyclesToUs(s64 cycles) {
- return std::chrono::microseconds(cycles * 1000 / detail::BASE_CLOCK_RATE_ADJUSTED);
-}
-
-} // namespace Core::Timing
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 4e61d4335..d3286b352 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -153,7 +153,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
std::vector<VirtualDir> patch_dirs = {sdmc_load_dir};
- if (load_dir != nullptr && load_dir->GetSize() > 0) {
+ if (load_dir != nullptr) {
const auto load_patch_dirs = load_dir->GetSubdirectories();
patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
}
@@ -354,8 +354,7 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
if ((type != ContentRecordType::Program && type != ContentRecordType::Data) ||
- ((load_dir == nullptr || load_dir->GetSize() <= 0) &&
- (sdmc_load_dir == nullptr || sdmc_load_dir->GetSize() <= 0))) {
+ (load_dir == nullptr && sdmc_load_dir == nullptr)) {
return;
}
@@ -496,7 +495,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
// General Mods (LayeredFS and IPS)
const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id);
- if (mod_dir != nullptr && mod_dir->GetSize() > 0) {
+ if (mod_dir != nullptr) {
for (const auto& mod : mod_dir->GetSubdirectories()) {
std::string types;
@@ -540,7 +539,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
// SDMC mod directory (RomFS LayeredFS)
const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
- if (sdmc_mod_dir != nullptr && sdmc_mod_dir->GetSize() > 0) {
+ if (sdmc_mod_dir != nullptr) {
std::string types;
if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs"))) {
AppendCommaIfNotEmpty(types, "LayeredExeFS");
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h
index 3226b884a..27f97c725 100644
--- a/src/core/file_sys/submission_package.h
+++ b/src/core/file_sys/submission_package.h
@@ -8,6 +8,7 @@
#include <set>
#include <vector>
#include "common/common_types.h"
+#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/vfs.h"
namespace Core::Crypto {
diff --git a/src/core/file_sys/system_archive/time_zone_binary.cpp b/src/core/file_sys/system_archive/time_zone_binary.cpp
index 85383998d..7c17bbefa 100644
--- a/src/core/file_sys/system_archive/time_zone_binary.cpp
+++ b/src/core/file_sys/system_archive/time_zone_binary.cpp
@@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <array>
#include <vector>
#include "common/swap.h"
@@ -9,656 +8,79 @@
#include "core/file_sys/vfs_vector.h"
#include "core/hle/service/time/time_zone_types.h"
-namespace FileSys::SystemArchive {
-
-static constexpr std::array<u8, 9633> LOCATION_NAMES{
- 0x43, 0x45, 0x54, 0x0d, 0x0a, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0d, 0x0a, 0x43, 0x75,
- 0x62, 0x61, 0x0d, 0x0a, 0x45, 0x45, 0x54, 0x0d, 0x0a, 0x45, 0x67, 0x79, 0x70, 0x74, 0x0d, 0x0a,
- 0x45, 0x69, 0x72, 0x65, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45,
- 0x44, 0x54, 0x0d, 0x0a, 0x47, 0x42, 0x0d, 0x0a, 0x47, 0x42, 0x2d, 0x45, 0x69, 0x72, 0x65, 0x0d,
- 0x0a, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54,
- 0x2d, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77,
- 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x48,
- 0x53, 0x54, 0x0d, 0x0a, 0x49, 0x63, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x49, 0x72, 0x61,
- 0x6e, 0x0d, 0x0a, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x0d, 0x0a, 0x4a, 0x61, 0x6d, 0x61, 0x69,
- 0x63, 0x61, 0x0d, 0x0a, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x4b, 0x77, 0x61, 0x6a, 0x61,
- 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x0d, 0x0a, 0x4d, 0x45, 0x54,
- 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0d, 0x0a,
- 0x4e, 0x61, 0x76, 0x61, 0x6a, 0x6f, 0x0d, 0x0a, 0x4e, 0x5a, 0x0d, 0x0a, 0x4e, 0x5a, 0x2d, 0x43,
- 0x48, 0x41, 0x54, 0x0d, 0x0a, 0x50, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x50, 0x6f, 0x72,
- 0x74, 0x75, 0x67, 0x61, 0x6c, 0x0d, 0x0a, 0x50, 0x52, 0x43, 0x0d, 0x0a, 0x50, 0x53, 0x54, 0x38,
- 0x50, 0x44, 0x54, 0x0d, 0x0a, 0x52, 0x4f, 0x43, 0x0d, 0x0a, 0x52, 0x4f, 0x4b, 0x0d, 0x0a, 0x53,
- 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
- 0x0d, 0x0a, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c,
- 0x0d, 0x0a, 0x55, 0x54, 0x43, 0x0d, 0x0a, 0x57, 0x2d, 0x53, 0x55, 0x0d, 0x0a, 0x57, 0x45, 0x54,
- 0x0d, 0x0a, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
- 0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
- 0x63, 0x63, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64,
- 0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x41, 0x73, 0x6d, 0x61, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
- 0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61,
- 0x6e, 0x67, 0x75, 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e,
- 0x6a, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73,
- 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74,
- 0x79, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a,
- 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
- 0x61, 0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0d, 0x0a, 0x41, 0x66,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x41,
- 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x66,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0d, 0x0a, 0x41,
- 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0d, 0x0a,
- 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0d,
- 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0d, 0x0a,
- 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x73, 0x62,
- 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61,
- 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61,
- 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75,
- 0x6d, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69,
- 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73,
- 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0d,
- 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c,
- 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0d,
- 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0d, 0x0a,
- 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68,
- 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61,
- 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0d,
- 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0d, 0x0a,
- 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0d, 0x0a, 0x41,
- 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41,
- 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0d,
- 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61,
- 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
- 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e,
- 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
- 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68,
- 0x6f, 0x74, 0x74, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67,
- 0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6d, 0x62, 0x75, 0x6b, 0x74, 0x75, 0x0d, 0x0a, 0x41, 0x66,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x66,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0d,
- 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69,
- 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62,
- 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63,
- 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x74, 0x69,
- 0x6b, 0x6f, 0x6b, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
- 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68,
- 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69,
- 0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f,
- 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56,
- 0x69, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
- 0x67, 0x6f, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
- 0x69, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65,
- 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f,
- 0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0d,
- 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48,
- 0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x68,
- 0x61, 0x76, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
- 0x73, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
- 0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x53, 0x61, 0x6c,
- 0x76, 0x61, 0x64, 0x6f, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
- 0x6e, 0x73, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0d,
- 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x57, 0x61,
- 0x79, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61,
- 0x63, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d,
- 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
- 0x75, 0x70, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61,
- 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70,
- 0x6f, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
- 0x75, 0x76, 0x69, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
- 0x61, 0x6c, 0x75, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
- 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
- 0x75, 0x6e, 0x65, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b,
- 0x6e, 0x6f, 0x78, 0x5f, 0x49, 0x4e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c,
- 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72,
- 0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61, 0x6d, 0x6f, 0x72, 0x6f,
- 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74,
- 0x6c, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e,
- 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65,
- 0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c,
- 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63,
- 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e,
- 0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f,
- 0x72, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69,
- 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d,
- 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e,
- 0x68, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e,
- 0x61, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
- 0x61, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
- 0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, 0x50,
- 0x72, 0x69, 0x6e, 0x63, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
- 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f,
- 0x53, 0x70, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
- 0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f,
- 0x52, 0x69, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52,
- 0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63,
- 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x73, 0x61, 0x72,
- 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74,
- 0x61, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61,
- 0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69,
- 0x6e, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f,
- 0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x68, 0x69, 0x70, 0x72, 0x6f, 0x63, 0x6b, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65,
- 0x6c, 0x65, 0x6d, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74,
- 0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e,
- 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74,
- 0x5f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
- 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61,
- 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
- 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f,
- 0x6e, 0x74, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72,
- 0x74, 0x6f, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61,
- 0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
- 0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e,
- 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
- 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69,
- 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
- 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74,
- 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x64, 0x52, 0x69, 0x76, 0x61, 0x64, 0x61, 0x76,
- 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
- 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
- 0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f,
- 0x6a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
- 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
- 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
- 0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
- 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75,
- 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
- 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x0d, 0x0a,
- 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e,
- 0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
- 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68,
- 0x75, 0x61, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
- 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c,
- 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
- 0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67,
- 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
- 0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54,
- 0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
- 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, 0x0d,
- 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
- 0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x61,
- 0x6d, 0x61, 0x63, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
- 0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65,
- 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63,
- 0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a, 0x41,
- 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b,
- 0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
- 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
- 0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
- 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65,
- 0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
- 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72,
- 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6e, 0x74,
- 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55,
- 0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
- 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0d, 0x0a, 0x41, 0x6e,
- 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0d,
- 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75,
- 0x72, 0x64, 0x6f, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
- 0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
- 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61,
- 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x50, 0x6f, 0x6c,
- 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79,
- 0x6f, 0x77, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
- 0x54, 0x72, 0x6f, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63,
- 0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63,
- 0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41,
- 0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61,
- 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0d, 0x0a,
- 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73,
- 0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68,
- 0x6b, 0x68, 0x61, 0x62, 0x61, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79,
- 0x72, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61,
- 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0d,
- 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42,
- 0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69,
- 0x72, 0x75, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65,
- 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0d, 0x0a,
- 0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
- 0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x43, 0x68, 0x6f, 0x6e, 0x67, 0x71, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x43, 0x68, 0x75, 0x6e, 0x67, 0x6b, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
- 0x61, 0x63, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73,
- 0x63, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0d,
- 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73,
- 0x68, 0x61, 0x6e, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61,
- 0x67, 0x75, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61,
- 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x62, 0x69, 0x6e, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x5f, 0x43,
- 0x68, 0x69, 0x5f, 0x4d, 0x69, 0x6e, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72,
- 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x73, 0x74, 0x61,
- 0x6e, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72,
- 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72,
- 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65,
- 0x6d, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69,
- 0x61, 0x2f, 0x4b, 0x61, 0x73, 0x68, 0x67, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
- 0x4b, 0x61, 0x74, 0x68, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
- 0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
- 0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x6f,
- 0x6c, 0x6b, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73,
- 0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75,
- 0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
- 0x75, 0x77, 0x61, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61,
- 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69,
- 0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75,
- 0x73, 0x63, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73,
- 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a,
- 0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
- 0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d,
- 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0d, 0x0a,
- 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0d, 0x0a,
- 0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0d, 0x0a,
- 0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x51, 0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52,
- 0x69, 0x79, 0x61, 0x64, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67,
- 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69,
- 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e,
- 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73,
- 0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x73,
- 0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
- 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x73,
- 0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
- 0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65,
- 0x6c, 0x5f, 0x41, 0x76, 0x69, 0x76, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
- 0x6d, 0x62, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68,
- 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
- 0x55, 0x6a, 0x75, 0x6e, 0x67, 0x5f, 0x50, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x67, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0d,
- 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x6e, 0x5f, 0x42, 0x61, 0x74, 0x6f, 0x72,
- 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x73,
- 0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x73,
- 0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a,
- 0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73,
- 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
- 0x59, 0x65, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
- 0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
- 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x74,
- 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0d, 0x0a,
- 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0d,
- 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56,
- 0x65, 0x72, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46,
- 0x61, 0x65, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
- 0x46, 0x61, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
- 0x4a, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
- 0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
- 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0d,
- 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f,
- 0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
- 0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
- 0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0d, 0x0a, 0x41,
- 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x43, 0x54, 0x0d, 0x0a, 0x41, 0x75,
- 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65,
- 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73,
- 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
- 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x75, 0x73,
- 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x62, 0x65, 0x72, 0x72, 0x61, 0x0d,
- 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, 0x69,
- 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x72,
- 0x77, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45,
- 0x75, 0x63, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
- 0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
- 0x61, 0x2f, 0x4c, 0x48, 0x49, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
- 0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72,
- 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0d, 0x0a,
- 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75,
- 0x72, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4e,
- 0x6f, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
- 0x4e, 0x53, 0x57, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
- 0x65, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
- 0x51, 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74,
- 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73,
- 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0d, 0x0a, 0x41,
- 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69,
- 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x63,
- 0x74, 0x6f, 0x72, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
- 0x2f, 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
- 0x2f, 0x59, 0x61, 0x6e, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61,
- 0x7a, 0x69, 0x6c, 0x2f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c,
- 0x2f, 0x44, 0x65, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a,
- 0x69, 0x6c, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f,
- 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x41, 0x74, 0x6c,
- 0x61, 0x6e, 0x74, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x43, 0x65,
- 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61,
- 0x73, 0x74, 0x2d, 0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d,
- 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x0d,
- 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e,
- 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e,
- 0x64, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x50, 0x61,
- 0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x53, 0x61,
- 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61,
- 0x64, 0x61, 0x2f, 0x59, 0x75, 0x6b, 0x6f, 0x6e, 0x0d, 0x0a, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x2f,
- 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x68, 0x69,
- 0x6c, 0x65, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
- 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
- 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0d, 0x0a,
- 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
- 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
- 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0d, 0x0a, 0x45,
- 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
- 0x54, 0x2b, 0x34, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0d, 0x0a,
- 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
- 0x4d, 0x54, 0x2b, 0x37, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0d,
- 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
- 0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31,
- 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74,
- 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
- 0x54, 0x2d, 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33,
- 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0d, 0x0a, 0x45, 0x74,
- 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
- 0x2d, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0d, 0x0a, 0x45,
- 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x35, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
- 0x54, 0x2d, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0d, 0x0a,
- 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
- 0x4d, 0x54, 0x2d, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a,
- 0x45, 0x74, 0x63, 0x2f, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x45,
- 0x74, 0x63, 0x2f, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x6e, 0x69, 0x76,
- 0x65, 0x72, 0x73, 0x61, 0x6c, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0d, 0x0a,
- 0x45, 0x74, 0x63, 0x2f, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
- 0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
- 0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
- 0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
- 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72,
- 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x66, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72,
- 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x45, 0x75,
- 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72,
- 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0d, 0x0a,
- 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0d,
- 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73,
- 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65,
- 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e,
- 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73,
- 0x69, 0x6e, 0x61, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70,
- 0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
- 0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
- 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
- 0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
- 0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
- 0x70, 0x65, 0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0d, 0x0a,
- 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0d,
- 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x0d, 0x0a,
- 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72,
- 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0d,
- 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x0d, 0x0a, 0x45,
- 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
- 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0d, 0x0a,
- 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0d, 0x0a, 0x45,
- 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67,
- 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69, 0x64, 0x0d,
- 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x45,
- 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0d,
- 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0d, 0x0a, 0x45,
- 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x0d, 0x0a, 0x45, 0x75,
- 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72,
- 0x6f, 0x70, 0x65, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72,
- 0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
- 0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50,
- 0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
- 0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
- 0x52, 0x69, 0x67, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d,
- 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61,
- 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72,
- 0x69, 0x6e, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61,
- 0x6a, 0x65, 0x76, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72,
- 0x61, 0x74, 0x6f, 0x76, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d,
- 0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
- 0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53,
- 0x6f, 0x66, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f,
- 0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
- 0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
- 0x69, 0x72, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69,
- 0x72, 0x61, 0x73, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55,
- 0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
- 0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
- 0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
- 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
- 0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
- 0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
- 0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
- 0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
- 0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a,
- 0x61, 0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
- 0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
- 0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0d, 0x0a, 0x49,
- 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
- 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0d, 0x0a,
- 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
- 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
- 0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, 0x6e, 0x0d, 0x0a, 0x49,
- 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x68, 0x65, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69,
- 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
- 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x49,
- 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0d, 0x0a, 0x49,
- 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x4d,
- 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x4e, 0x6f, 0x72, 0x74, 0x65, 0x0d,
- 0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x53, 0x75, 0x72, 0x0d,
- 0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x0d,
- 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0d, 0x0a, 0x50,
- 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
- 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e,
- 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43,
- 0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
- 0x43, 0x68, 0x75, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
- 0x61, 0x73, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
- 0x66, 0x61, 0x74, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e,
- 0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
- 0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
- 0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
- 0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
- 0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63,
- 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61,
- 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61,
- 0x6c, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0d,
- 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c,
- 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73,
- 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72,
- 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
- 0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
- 0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
- 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
- 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x0d, 0x0a, 0x50,
- 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, 0x0d, 0x0a, 0x50,
- 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0d, 0x0a, 0x50, 0x61,
- 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
- 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63,
- 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63,
- 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0d, 0x0a,
- 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0d, 0x0a, 0x50,
- 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x0d,
- 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x68, 0x6e, 0x70, 0x65, 0x69,
- 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65,
- 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d,
- 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
- 0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
- 0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
- 0x69, 0x63, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
- 0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
- 0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, 0x77, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
- 0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63,
- 0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
- 0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
- 0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
- 0x2f, 0x59, 0x61, 0x70, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x0d,
- 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
- 0x2f, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x43, 0x65, 0x6e,
- 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x49, 0x6e,
- 0x64, 0x69, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72,
- 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x0d, 0x0a, 0x55, 0x53,
- 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2d, 0x53, 0x74, 0x61, 0x72, 0x6b, 0x65, 0x0d,
- 0x0a, 0x55, 0x53, 0x2f, 0x4d, 0x69, 0x63, 0x68, 0x69, 0x67, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
- 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61,
- 0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
- 0x63, 0x2d, 0x4e, 0x65, 0x77, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d,
- 0x0a};
+#include "nx_tzdb.h"
-static VirtualFile GenerateDefaultTimeZoneFile() {
- struct TimeZoneInfo {
- s64_be at;
- std::array<u8, 7> padding1;
- std::array<char, 4> time_zone_chars;
- std::array<u8, 2> padding2;
- std::array<char, 6> time_zone_name;
- };
+namespace FileSys::SystemArchive {
- VirtualFile file{std::make_shared<VectorVfsFile>(
- std::vector<u8>(sizeof(Service::Time::TimeZone::TzifHeader) + sizeof(TimeZoneInfo)),
- "GMT")};
+const static std::map<std::string, const std::map<const char*, const std::vector<u8>>&>
+ tzdb_zoneinfo_dirs = {{"Africa", NxTzdb::africa},
+ {"America", NxTzdb::america},
+ {"Antarctica", NxTzdb::antarctica},
+ {"Arctic", NxTzdb::arctic},
+ {"Asia", NxTzdb::asia},
+ {"Atlantic", NxTzdb::atlantic},
+ {"Australia", NxTzdb::australia},
+ {"Brazil", NxTzdb::brazil},
+ {"Canada", NxTzdb::canada},
+ {"Chile", NxTzdb::chile},
+ {"Etc", NxTzdb::etc},
+ {"Europe", NxTzdb::europe},
+ {"Indian", NxTzdb::indian},
+ {"Mexico", NxTzdb::mexico},
+ {"Pacific", NxTzdb::pacific},
+ {"US", NxTzdb::us}};
- const Service::Time::TimeZone::TzifHeader header{
- .magic = 0x545a6966,
- .version = 0x32,
- .ttis_gmt_count = 1,
- .ttis_std_count = 1,
- .time_count = 1,
- .type_count = 1,
- .char_count = 4,
- };
- file->WriteObject(header, 0);
+const static std::map<std::string, const std::map<const char*, const std::vector<u8>>&>
+ tzdb_america_dirs = {{"Argentina", NxTzdb::america_argentina},
+ {"Indiana", NxTzdb::america_indiana},
+ {"Kentucky", NxTzdb::america_kentucky},
+ {"North_Dakota", NxTzdb::america_north_dakota}};
- const TimeZoneInfo time_zone_info{
- .at = 0xf8,
- .padding1 = {},
- .time_zone_chars = {'G', 'M', 'T', '\0'},
- .padding2 = {},
- .time_zone_name = {'\n', 'G', 'M', 'T', '0', '\n'},
- };
- file->WriteObject(time_zone_info, sizeof(Service::Time::TimeZone::TzifHeader));
+static void GenerateFiles(std::vector<VirtualFile>& directory,
+ const std::map<const char*, const std::vector<u8>>& files) {
+ for (const auto& [filename, data] : files) {
+ const auto data_copy{data};
+ const std::string filename_copy{filename};
+ VirtualFile file{
+ std::make_shared<VectorVfsFile>(std::move(data_copy), std::move(filename_copy))};
+ directory.push_back(file);
+ }
+}
- return file;
+static std::vector<VirtualFile> GenerateZoneinfoFiles() {
+ std::vector<VirtualFile> zoneinfo_files;
+ GenerateFiles(zoneinfo_files, NxTzdb::zoneinfo);
+ return zoneinfo_files;
}
VirtualDir TimeZoneBinary() {
- std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>(
- std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{},
- "zoneinfo")};
- std::vector<VirtualFile> root_files{MakeArrayFile(LOCATION_NAMES, "binaryList.txt")};
+ std::vector<VirtualDir> america_sub_dirs;
+ for (const auto& [dir_name, files] : tzdb_america_dirs) {
+ std::vector<VirtualFile> vfs_files;
+ GenerateFiles(vfs_files, files);
+ america_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(
+ std::move(vfs_files), std::vector<VirtualDir>{}, dir_name));
+ }
+
+ std::vector<VirtualDir> zoneinfo_sub_dirs;
+ for (const auto& [dir_name, files] : tzdb_zoneinfo_dirs) {
+ std::vector<VirtualFile> vfs_files;
+ GenerateFiles(vfs_files, files);
+ if (dir_name == "America") {
+ zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(
+ std::move(vfs_files), std::move(america_sub_dirs), dir_name));
+ } else {
+ zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(
+ std::move(vfs_files), std::vector<VirtualDir>{}, dir_name));
+ }
+ }
+
+ std::vector<VirtualDir> zoneinfo_dir{std::make_shared<VectorVfsDirectory>(
+ GenerateZoneinfoFiles(), std::move(zoneinfo_sub_dirs), "zoneinfo")};
+ std::vector<VirtualFile> root_files;
+ GenerateFiles(root_files, NxTzdb::base);
- return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(root_dirs),
+ return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(zoneinfo_dir),
"data");
}
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp
index 853b893a1..311a59e5f 100644
--- a/src/core/file_sys/vfs_concat.cpp
+++ b/src/core/file_sys/vfs_concat.cpp
@@ -150,23 +150,29 @@ std::size_t ConcatenatedVfsFile::Read(u8* data, std::size_t length, std::size_t
while (cur_length > 0 && it != concatenation_map.end()) {
// Check if we can read the file at this position.
const auto& file = it->file;
- const u64 file_offset = it->offset;
+ const u64 map_offset = it->offset;
const u64 file_size = file->GetSize();
- if (cur_offset >= file_offset + file_size) {
+ if (cur_offset > map_offset + file_size) {
// Entirely out of bounds read.
break;
}
// Read the file at this position.
- const u64 intended_read_size = std::min<u64>(cur_length, file_size);
+ const u64 file_seek = cur_offset - map_offset;
+ const u64 intended_read_size = std::min<u64>(cur_length, file_size - file_seek);
const u64 actual_read_size =
- file->Read(data + (cur_offset - offset), intended_read_size, cur_offset - file_offset);
+ file->Read(data + (cur_offset - offset), intended_read_size, file_seek);
// Update tracking.
cur_offset += actual_read_size;
cur_length -= actual_read_size;
it++;
+
+ // If we encountered a short read, we're done.
+ if (actual_read_size < intended_read_size) {
+ break;
+ }
}
return cur_offset - offset;
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index cc0076238..b0515ec05 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -10,6 +10,7 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/logging/log.h"
+#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_real.h"
// For FileTimeStampRaw
@@ -25,6 +26,8 @@ namespace FS = Common::FS;
namespace {
+constexpr size_t MaxOpenFiles = 512;
+
constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) {
switch (mode) {
case Mode::Read:
@@ -70,31 +73,42 @@ VfsEntryType RealVfsFilesystem::GetEntryType(std::string_view path_) const {
return VfsEntryType::File;
}
-VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
+VirtualFile RealVfsFilesystem::OpenFileFromEntry(std::string_view path_, std::optional<u64> size,
+ Mode perms) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
+ std::scoped_lock lk{list_lock};
- if (const auto weak_iter = cache.find(path); weak_iter != cache.cend()) {
- const auto& weak = weak_iter->second;
-
- if (!weak.expired()) {
- return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, weak.lock(), path, perms));
+ if (auto it = cache.find(path); it != cache.end()) {
+ if (auto file = it->second.lock(); file) {
+ return file;
}
}
- auto backing = FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile);
-
- if (!backing) {
+ if (!size && !FS::IsFile(path)) {
return nullptr;
}
- cache.insert_or_assign(path, std::move(backing));
+ auto reference = std::make_unique<FileReference>();
+ this->InsertReferenceIntoListLocked(*reference);
- // Cannot use make_shared as RealVfsFile constructor is private
- return std::shared_ptr<RealVfsFile>(new RealVfsFile(*this, backing, path, perms));
+ auto file = std::shared_ptr<RealVfsFile>(
+ new RealVfsFile(*this, std::move(reference), path, perms, size));
+ cache[path] = file;
+
+ return file;
+}
+
+VirtualFile RealVfsFilesystem::OpenFile(std::string_view path_, Mode perms) {
+ return OpenFileFromEntry(path_, {}, perms);
}
VirtualFile RealVfsFilesystem::CreateFile(std::string_view path_, Mode perms) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
+ {
+ std::scoped_lock lk{list_lock};
+ cache.erase(path);
+ }
+
// Current usages of CreateFile expect to delete the contents of an existing file.
if (FS::IsFile(path)) {
FS::IOFile temp{path, FS::FileAccessMode::Write, FS::FileType::BinaryFile};
@@ -123,51 +137,28 @@ VirtualFile RealVfsFilesystem::CopyFile(std::string_view old_path_, std::string_
VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_view new_path_) {
const auto old_path = FS::SanitizePath(old_path_, FS::DirectorySeparator::PlatformDefault);
const auto new_path = FS::SanitizePath(new_path_, FS::DirectorySeparator::PlatformDefault);
- const auto cached_file_iter = cache.find(old_path);
-
- if (cached_file_iter != cache.cend()) {
- auto file = cached_file_iter->second.lock();
-
- if (!cached_file_iter->second.expired()) {
- file->Close();
- }
-
- if (!FS::RenameFile(old_path, new_path)) {
- return nullptr;
- }
-
+ {
+ std::scoped_lock lk{list_lock};
cache.erase(old_path);
- file->Open(new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile);
- if (file->IsOpen()) {
- cache.insert_or_assign(new_path, std::move(file));
- } else {
- LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", new_path);
- }
- } else {
- ASSERT(false);
+ cache.erase(new_path);
+ }
+ if (!FS::RenameFile(old_path, new_path)) {
return nullptr;
}
-
return OpenFile(new_path, Mode::ReadWrite);
}
bool RealVfsFilesystem::DeleteFile(std::string_view path_) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
- const auto cached_iter = cache.find(path);
-
- if (cached_iter != cache.cend()) {
- if (!cached_iter->second.expired()) {
- cached_iter->second.lock()->Close();
- }
+ {
+ std::scoped_lock lk{list_lock};
cache.erase(path);
}
-
return FS::RemoveFile(path);
}
VirtualDir RealVfsFilesystem::OpenDirectory(std::string_view path_, Mode perms) {
const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
- // Cannot use make_shared as RealVfsDirectory constructor is private
return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
}
@@ -176,7 +167,6 @@ VirtualDir RealVfsFilesystem::CreateDirectory(std::string_view path_, Mode perms
if (!FS::CreateDirs(path)) {
return nullptr;
}
- // Cannot use make_shared as RealVfsDirectory constructor is private
return std::shared_ptr<RealVfsDirectory>(new RealVfsDirectory(*this, path, perms));
}
@@ -194,73 +184,112 @@ VirtualDir RealVfsFilesystem::MoveDirectory(std::string_view old_path_,
if (!FS::RenameDir(old_path, new_path)) {
return nullptr;
}
+ return OpenDirectory(new_path, Mode::ReadWrite);
+}
- for (auto& kv : cache) {
- // If the path in the cache doesn't start with old_path, then bail on this file.
- if (kv.first.rfind(old_path, 0) != 0) {
- continue;
- }
+bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {
+ const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
+ return FS::RemoveDirRecursively(path);
+}
- const auto file_old_path =
- FS::SanitizePath(kv.first, FS::DirectorySeparator::PlatformDefault);
- auto file_new_path = FS::SanitizePath(new_path + '/' + kv.first.substr(old_path.size()),
- FS::DirectorySeparator::PlatformDefault);
- const auto& cached = cache[file_old_path];
+std::unique_lock<std::mutex> RealVfsFilesystem::RefreshReference(const std::string& path,
+ Mode perms,
+ FileReference& reference) {
+ std::unique_lock lk{list_lock};
- if (cached.expired()) {
- continue;
- }
+ // Temporarily remove from list.
+ this->RemoveReferenceFromListLocked(reference);
+
+ // Restore file if needed.
+ if (!reference.file) {
+ this->EvictSingleReferenceLocked();
- auto file = cached.lock();
- cache.erase(file_old_path);
- file->Open(file_new_path, FS::FileAccessMode::Read, FS::FileType::BinaryFile);
- if (file->IsOpen()) {
- cache.insert_or_assign(std::move(file_new_path), std::move(file));
- } else {
- LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", file_new_path);
+ reference.file =
+ FS::FileOpen(path, ModeFlagsToFileAccessMode(perms), FS::FileType::BinaryFile);
+ if (reference.file) {
+ num_open_files++;
}
}
- return OpenDirectory(new_path, Mode::ReadWrite);
+ // Reinsert into list.
+ this->InsertReferenceIntoListLocked(reference);
+
+ return lk;
}
-bool RealVfsFilesystem::DeleteDirectory(std::string_view path_) {
- const auto path = FS::SanitizePath(path_, FS::DirectorySeparator::PlatformDefault);
+void RealVfsFilesystem::DropReference(std::unique_ptr<FileReference>&& reference) {
+ std::scoped_lock lk{list_lock};
- for (auto& kv : cache) {
- // If the path in the cache doesn't start with path, then bail on this file.
- if (kv.first.rfind(path, 0) != 0) {
- continue;
- }
+ // Remove from list.
+ this->RemoveReferenceFromListLocked(*reference);
- const auto& entry = cache[kv.first];
- if (!entry.expired()) {
- entry.lock()->Close();
- }
+ // Close the file.
+ if (reference->file) {
+ reference->file.reset();
+ num_open_files--;
+ }
+}
- cache.erase(kv.first);
+void RealVfsFilesystem::EvictSingleReferenceLocked() {
+ if (num_open_files < MaxOpenFiles || open_references.empty()) {
+ return;
}
- return FS::RemoveDirRecursively(path);
+ // Get and remove from list.
+ auto& reference = open_references.back();
+ this->RemoveReferenceFromListLocked(reference);
+
+ // Close the file.
+ if (reference.file) {
+ reference.file.reset();
+ num_open_files--;
+ }
+
+ // Reinsert into closed list.
+ this->InsertReferenceIntoListLocked(reference);
+}
+
+void RealVfsFilesystem::InsertReferenceIntoListLocked(FileReference& reference) {
+ if (reference.file) {
+ open_references.push_front(reference);
+ } else {
+ closed_references.push_front(reference);
+ }
}
-RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::shared_ptr<FS::IOFile> backing_,
- const std::string& path_, Mode perms_)
- : base(base_), backing(std::move(backing_)), path(path_), parent_path(FS::GetParentPath(path_)),
- path_components(FS::SplitPathComponents(path_)), perms(perms_) {}
+void RealVfsFilesystem::RemoveReferenceFromListLocked(FileReference& reference) {
+ if (reference.file) {
+ open_references.erase(open_references.iterator_to(reference));
+ } else {
+ closed_references.erase(closed_references.iterator_to(reference));
+ }
+}
-RealVfsFile::~RealVfsFile() = default;
+RealVfsFile::RealVfsFile(RealVfsFilesystem& base_, std::unique_ptr<FileReference> reference_,
+ const std::string& path_, Mode perms_, std::optional<u64> size_)
+ : base(base_), reference(std::move(reference_)), path(path_),
+ parent_path(FS::GetParentPath(path_)), path_components(FS::SplitPathComponents(path_)),
+ size(size_), perms(perms_) {}
+
+RealVfsFile::~RealVfsFile() {
+ base.DropReference(std::move(reference));
+}
std::string RealVfsFile::GetName() const {
return path_components.back();
}
std::size_t RealVfsFile::GetSize() const {
- return backing->GetSize();
+ if (size) {
+ return *size;
+ }
+ return FS::GetSize(path);
}
bool RealVfsFile::Resize(std::size_t new_size) {
- return backing->SetSize(new_size);
+ size.reset();
+ auto lk = base.RefreshReference(path, perms, *reference);
+ return reference->file ? reference->file->SetSize(new_size) : false;
}
VirtualDir RealVfsFile::GetContainingDirectory() const {
@@ -276,27 +305,26 @@ bool RealVfsFile::IsReadable() const {
}
std::size_t RealVfsFile::Read(u8* data, std::size_t length, std::size_t offset) const {
- if (!backing->Seek(static_cast<s64>(offset))) {
+ auto lk = base.RefreshReference(path, perms, *reference);
+ if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) {
return 0;
}
- return backing->ReadSpan(std::span{data, length});
+ return reference->file->ReadSpan(std::span{data, length});
}
std::size_t RealVfsFile::Write(const u8* data, std::size_t length, std::size_t offset) {
- if (!backing->Seek(static_cast<s64>(offset))) {
+ size.reset();
+ auto lk = base.RefreshReference(path, perms, *reference);
+ if (!reference->file || !reference->file->Seek(static_cast<s64>(offset))) {
return 0;
}
- return backing->WriteSpan(std::span{data, length});
+ return reference->file->WriteSpan(std::span{data, length});
}
bool RealVfsFile::Rename(std::string_view name) {
return base.MoveFile(path, parent_path + '/' + std::string(name)) != nullptr;
}
-void RealVfsFile::Close() {
- backing->Close();
-}
-
// TODO(DarkLordZach): MSVC would not let me combine the following two functions using 'if
// constexpr' because there is a compile error in the branch not used.
@@ -308,10 +336,11 @@ std::vector<VirtualFile> RealVfsDirectory::IterateEntries<RealVfsFile, VfsFile>(
std::vector<VirtualFile> out;
- const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) {
- const auto full_path_string = FS::PathToUTF8String(full_path);
+ const FS::DirEntryCallable callback = [this,
+ &out](const std::filesystem::directory_entry& entry) {
+ const auto full_path_string = FS::PathToUTF8String(entry.path());
- out.emplace_back(base.OpenFile(full_path_string, perms));
+ out.emplace_back(base.OpenFileFromEntry(full_path_string, entry.file_size(), perms));
return true;
};
@@ -329,8 +358,9 @@ std::vector<VirtualDir> RealVfsDirectory::IterateEntries<RealVfsDirectory, VfsDi
std::vector<VirtualDir> out;
- const FS::DirEntryCallable callback = [this, &out](const std::filesystem::path& full_path) {
- const auto full_path_string = FS::PathToUTF8String(full_path);
+ const FS::DirEntryCallable callback = [this,
+ &out](const std::filesystem::directory_entry& entry) {
+ const auto full_path_string = FS::PathToUTF8String(entry.path());
out.emplace_back(base.OpenDirectory(full_path_string, perms));
@@ -482,12 +512,10 @@ std::map<std::string, VfsEntryType, std::less<>> RealVfsDirectory::GetEntries()
std::map<std::string, VfsEntryType, std::less<>> out;
- const FS::DirEntryCallable callback = [&out](const std::filesystem::path& full_path) {
- const auto filename = FS::PathToUTF8String(full_path.filename());
-
+ const FS::DirEntryCallable callback = [&out](const std::filesystem::directory_entry& entry) {
+ const auto filename = FS::PathToUTF8String(entry.path().filename());
out.insert_or_assign(filename,
- FS::IsDir(full_path) ? VfsEntryType::Directory : VfsEntryType::File);
-
+ entry.is_directory() ? VfsEntryType::Directory : VfsEntryType::File);
return true;
};
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index b92c84316..26ea7df62 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -3,8 +3,11 @@
#pragma once
+#include <map>
+#include <mutex>
+#include <optional>
#include <string_view>
-#include <boost/container/flat_map.hpp>
+#include "common/intrusive_list.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/vfs.h"
@@ -14,6 +17,13 @@ class IOFile;
namespace FileSys {
+struct FileReference : public Common::IntrusiveListBaseNode<FileReference> {
+ std::shared_ptr<Common::FS::IOFile> file{};
+};
+
+class RealVfsFile;
+class RealVfsDirectory;
+
class RealVfsFilesystem : public VfsFilesystem {
public:
RealVfsFilesystem();
@@ -35,7 +45,28 @@ public:
bool DeleteDirectory(std::string_view path) override;
private:
- boost::container::flat_map<std::string, std::weak_ptr<Common::FS::IOFile>> cache;
+ using ReferenceListType = Common::IntrusiveListBaseTraits<FileReference>::ListType;
+ std::map<std::string, std::weak_ptr<VfsFile>, std::less<>> cache;
+ ReferenceListType open_references;
+ ReferenceListType closed_references;
+ std::mutex list_lock;
+ size_t num_open_files{};
+
+private:
+ friend class RealVfsFile;
+ std::unique_lock<std::mutex> RefreshReference(const std::string& path, Mode perms,
+ FileReference& reference);
+ void DropReference(std::unique_ptr<FileReference>&& reference);
+
+private:
+ friend class RealVfsDirectory;
+ VirtualFile OpenFileFromEntry(std::string_view path, std::optional<u64> size,
+ Mode perms = Mode::Read);
+
+private:
+ void EvictSingleReferenceLocked();
+ void InsertReferenceIntoListLocked(FileReference& reference);
+ void RemoveReferenceFromListLocked(FileReference& reference);
};
// An implementation of VfsFile that represents a file on the user's computer.
@@ -57,16 +88,15 @@ public:
bool Rename(std::string_view name) override;
private:
- RealVfsFile(RealVfsFilesystem& base, std::shared_ptr<Common::FS::IOFile> backing,
- const std::string& path, Mode perms = Mode::Read);
-
- void Close();
+ RealVfsFile(RealVfsFilesystem& base, std::unique_ptr<FileReference> reference,
+ const std::string& path, Mode perms = Mode::Read, std::optional<u64> size = {});
RealVfsFilesystem& base;
- std::shared_ptr<Common::FS::IOFile> backing;
+ std::unique_ptr<FileReference> reference;
std::string path;
std::string parent_path;
std::vector<std::string> path_components;
+ std::optional<u64> size;
Mode perms;
};
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 0a7777732..1ebc32c1e 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -149,12 +149,16 @@ void EmulatedController::LoadDevices() {
camera_params[0] = right_joycon;
camera_params[0].Set("camera", true);
- camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"};
- ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"};
- nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
nfc_params[1] = right_joycon;
nfc_params[1].Set("nfc", true);
+ // Only map virtual devices to the first controller
+ if (npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld) {
+ camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"};
+ ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"};
+ nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"};
+ }
+
output_params[LeftIndex] = left_joycon;
output_params[RightIndex] = right_joycon;
output_params[2] = camera_params[1];
@@ -1176,10 +1180,7 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
return;
}
- controller.nfc_state = {
- controller.nfc_values.state,
- controller.nfc_values.data,
- };
+ controller.nfc_state = controller.nfc_values;
}
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
@@ -1249,6 +1250,11 @@ Common::Input::DriverResult EmulatedController::SetPollingMode(
const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode);
const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode);
+ // Restore previous state
+ if (mapped_nfc_result != Common::Input::DriverResult::Success) {
+ right_output_device->SetPollingMode(Common::Input::PollingMode::Active);
+ }
+
if (virtual_nfc_result == Common::Input::DriverResult::Success) {
return virtual_nfc_result;
}
@@ -1308,6 +1314,79 @@ bool EmulatedController::HasNfc() const {
return is_connected && (has_virtual_nfc && is_virtual_nfc_supported);
}
+bool EmulatedController::AddNfcHandle() {
+ nfc_handles++;
+ return SetPollingMode(EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::NFC) ==
+ Common::Input::DriverResult::Success;
+}
+
+bool EmulatedController::RemoveNfcHandle() {
+ nfc_handles--;
+ if (nfc_handles <= 0) {
+ return SetPollingMode(EmulatedDeviceIndex::RightIndex,
+ Common::Input::PollingMode::Active) ==
+ Common::Input::DriverResult::Success;
+ }
+ return true;
+}
+
+bool EmulatedController::StartNfcPolling() {
+ auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
+ auto& nfc_virtual_output_device = output_devices[3];
+
+ const auto device_result = nfc_output_device->StartNfcPolling();
+ const auto virtual_device_result = nfc_virtual_output_device->StartNfcPolling();
+
+ return device_result == Common::Input::NfcState::Success ||
+ virtual_device_result == Common::Input::NfcState::Success;
+}
+
+bool EmulatedController::StopNfcPolling() {
+ auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
+ auto& nfc_virtual_output_device = output_devices[3];
+
+ const auto device_result = nfc_output_device->StopNfcPolling();
+ const auto virtual_device_result = nfc_virtual_output_device->StopNfcPolling();
+
+ return device_result == Common::Input::NfcState::Success ||
+ virtual_device_result == Common::Input::NfcState::Success;
+}
+
+bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) {
+ auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
+ auto& nfc_virtual_output_device = output_devices[3];
+
+ if (nfc_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success) {
+ return true;
+ }
+
+ return nfc_virtual_output_device->ReadAmiiboData(data) == Common::Input::NfcState::Success;
+}
+
+bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& request,
+ Common::Input::MifareRequest& out_data) {
+ auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
+ auto& nfc_virtual_output_device = output_devices[3];
+
+ if (nfc_output_device->ReadMifareData(request, out_data) == Common::Input::NfcState::Success) {
+ return true;
+ }
+
+ return nfc_virtual_output_device->ReadMifareData(request, out_data) ==
+ Common::Input::NfcState::Success;
+}
+
+bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& request) {
+ auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
+ auto& nfc_virtual_output_device = output_devices[3];
+
+ if (nfc_output_device->WriteMifareData(request) == Common::Input::NfcState::Success) {
+ return true;
+ }
+
+ return nfc_virtual_output_device->WriteMifareData(request) == Common::Input::NfcState::Success;
+}
+
bool EmulatedController::WriteNfc(const std::vector<u8>& data) {
auto& nfc_output_device = output_devices[static_cast<std::size_t>(DeviceIndex::Right)];
auto& nfc_virtual_output_device = output_devices[3];
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 09fe1a0ab..d511e5fac 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -97,10 +97,7 @@ struct RingSensorForce {
f32 force;
};
-struct NfcState {
- Common::Input::NfcState state{};
- std::vector<u8> data{};
-};
+using NfcState = Common::Input::NfcStatus;
struct ControllerMotion {
Common::Vec3f accel{};
@@ -393,9 +390,31 @@ public:
/// Returns true if the device has nfc support
bool HasNfc() const;
+ /// Sets the joycon in nfc mode and increments the handle count
+ bool AddNfcHandle();
+
+ /// Decrements the handle count if zero sets the joycon in active mode
+ bool RemoveNfcHandle();
+
+ /// Start searching for nfc tags
+ bool StartNfcPolling();
+
+ /// Stop searching for nfc tags
+ bool StopNfcPolling();
+
+ /// Returns true if the nfc tag was readable
+ bool ReadAmiiboData(std::vector<u8>& data);
+
/// Returns true if the nfc tag was written
bool WriteNfc(const std::vector<u8>& data);
+ /// Returns true if the nfc tag was readable
+ bool ReadMifareData(const Common::Input::MifareRequest& request,
+ Common::Input::MifareRequest& out_data);
+
+ /// Returns true if the nfc tag was written
+ bool WriteMifareData(const Common::Input::MifareRequest& request);
+
/// Returns the led pattern corresponding to this emulated controller
LedPattern GetLedPattern() const;
@@ -532,6 +551,7 @@ private:
bool system_buttons_enabled{true};
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
u32 turbo_button_state{0};
+ std::size_t nfc_handles{0};
// Temporary values to avoid doing changes while the controller is in configuring mode
NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp
index 4ccb1c596..a05716fd8 100644
--- a/src/core/hid/input_converter.cpp
+++ b/src/core/hid/input_converter.cpp
@@ -299,11 +299,7 @@ Common::Input::NfcStatus TransformToNfc(const Common::Input::CallbackStatus& cal
Common::Input::NfcStatus nfc{};
switch (callback.type) {
case Common::Input::InputType::Nfc:
- nfc = {
- .state = callback.nfc_status,
- .data = callback.raw_data,
- };
- break;
+ return callback.nfc_status;
default:
LOG_ERROR(Input, "Conversion from type {} to NFC not implemented", callback.type);
break;
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index faa12b4f0..75ce5a23c 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -184,7 +184,8 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {
prev_highest_thread != highest_thread) [[likely]] {
if (prev_highest_thread != nullptr) [[likely]] {
IncrementScheduledCount(prev_highest_thread);
- prev_highest_thread->SetLastScheduledTick(m_kernel.System().CoreTiming().GetCPUTicks());
+ prev_highest_thread->SetLastScheduledTick(
+ m_kernel.System().CoreTiming().GetClockTicks());
}
if (m_state.should_count_idle) {
if (highest_thread != nullptr) [[likely]] {
@@ -351,7 +352,7 @@ void KScheduler::SwitchThread(KThread* next_thread) {
// Update the CPU time tracking variables.
const s64 prev_tick = m_last_context_switch_time;
- const s64 cur_tick = m_kernel.System().CoreTiming().GetCPUTicks();
+ const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks();
const s64 tick_diff = cur_tick - prev_tick;
cur_thread->AddCpuTime(m_core_id, tick_diff);
if (cur_process != nullptr) {
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp
index b7da3eee7..3e5b735b1 100644
--- a/src/core/hle/kernel/k_synchronization_object.cpp
+++ b/src/core/hle/kernel/k_synchronization_object.cpp
@@ -3,6 +3,7 @@
#include "common/assert.h"
#include "common/common_types.h"
+#include "common/scratch_buffer.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_synchronization_object.h"
@@ -75,7 +76,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
KSynchronizationObject** objects, const s32 num_objects,
s64 timeout) {
// Allocate space on stack for thread nodes.
- std::vector<ThreadListNode> thread_nodes(num_objects);
+ std::array<ThreadListNode, Svc::ArgumentHandleCountMax> thread_nodes;
// Prepare for wait.
KThread* thread = GetCurrentThreadPointer(kernel);
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 70480b725..adb6ec581 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -4,6 +4,8 @@
#include <algorithm>
#include <atomic>
#include <cinttypes>
+#include <condition_variable>
+#include <mutex>
#include <optional>
#include <vector>
@@ -907,7 +909,7 @@ Result KThread::SetActivity(Svc::ThreadActivity activity) {
R_SUCCEED();
}
-Result KThread::GetThreadContext3(std::vector<u8>& out) {
+Result KThread::GetThreadContext3(Common::ScratchBuffer<u8>& out) {
// Lock ourselves.
KScopedLightLock lk{m_activity_pause_lock};
@@ -925,15 +927,13 @@ Result KThread::GetThreadContext3(std::vector<u8>& out) {
// Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
auto context = GetContext64();
context.pstate &= 0xFF0FFE20;
-
- out.resize(sizeof(context));
+ out.resize_destructive(sizeof(context));
std::memcpy(out.data(), std::addressof(context), sizeof(context));
} else {
// Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
auto context = GetContext32();
context.cpsr &= 0xFF0FFE20;
-
- out.resize(sizeof(context));
+ out.resize_destructive(sizeof(context));
std::memcpy(out.data(), std::addressof(context), sizeof(context));
}
}
@@ -1313,7 +1313,8 @@ void KThread::RequestDummyThreadWait() {
ASSERT(this->IsDummyThread());
// We will block when the scheduler lock is released.
- m_dummy_thread_runnable.store(false);
+ std::scoped_lock lock{m_dummy_thread_mutex};
+ m_dummy_thread_runnable = false;
}
void KThread::DummyThreadBeginWait() {
@@ -1323,7 +1324,8 @@ void KThread::DummyThreadBeginWait() {
}
// Block until runnable is no longer false.
- m_dummy_thread_runnable.wait(false);
+ std::unique_lock lock{m_dummy_thread_mutex};
+ m_dummy_thread_cv.wait(lock, [this] { return m_dummy_thread_runnable; });
}
void KThread::DummyThreadEndWait() {
@@ -1331,8 +1333,11 @@ void KThread::DummyThreadEndWait() {
ASSERT(this->IsDummyThread());
// Wake up the waiting thread.
- m_dummy_thread_runnable.store(true);
- m_dummy_thread_runnable.notify_one();
+ {
+ std::scoped_lock lock{m_dummy_thread_mutex};
+ m_dummy_thread_runnable = true;
+ }
+ m_dummy_thread_cv.notify_one();
}
void KThread::BeginWait(KThreadQueue* queue) {
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index f9814ac8f..dd662b3f8 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -15,6 +15,7 @@
#include "common/intrusive_list.h"
#include "common/intrusive_red_black_tree.h"
+#include "common/scratch_buffer.h"
#include "common/spin_lock.h"
#include "core/arm/arm_interface.h"
#include "core/hle/kernel/k_affinity_mask.h"
@@ -567,7 +568,7 @@ public:
void RemoveWaiter(KThread* thread);
- Result GetThreadContext3(std::vector<u8>& out);
+ Result GetThreadContext3(Common::ScratchBuffer<u8>& out);
KThread* RemoveUserWaiterByKey(bool* out_has_waiters, KProcessAddress key) {
return this->RemoveWaiterByKey(out_has_waiters, key, false);
@@ -892,7 +893,9 @@ private:
std::shared_ptr<Common::Fiber> m_host_context{};
ThreadType m_thread_type{};
StepState m_step_state{};
- std::atomic<bool> m_dummy_thread_runnable{true};
+ bool m_dummy_thread_runnable{true};
+ std::mutex m_dummy_thread_mutex{};
+ std::condition_variable m_dummy_thread_cv{};
// For debugging
std::vector<KSynchronizationObject*> m_wait_objects_for_debugging{};
diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp
index 2b2c878b5..445cdd87b 100644
--- a/src/core/hle/kernel/svc/svc_info.cpp
+++ b/src/core/hle/kernel/svc/svc_info.cpp
@@ -199,9 +199,9 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
const u64 thread_ticks = current_thread->GetCpuTime();
- out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks);
+ out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
- out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks;
+ out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;
}
*result = out_ticks;
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index ea03068aa..60247df2e 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
+#include "common/scratch_buffer.h"
#include "core/core.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_process.h"
@@ -45,11 +46,11 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
ResultInvalidPointer);
- std::vector<Handle> handles(num_handles);
+ std::array<Handle, Svc::ArgumentHandleCountMax> handles;
GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
// Convert handle list to object table.
- std::vector<KSynchronizationObject*> objs(num_handles);
+ std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(),
num_handles),
ResultInvalidHandle);
@@ -80,7 +81,7 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
// Wait for an object.
s32 index;
Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(),
- static_cast<s32>(objs.size()), timeout_ns);
+ num_handles, timeout_ns);
if (result == ResultTimedOut) {
R_RETURN(result);
}
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 04d65f0bd..53df5bcd8 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
+#include "common/scratch_buffer.h"
#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_readable_event.h"
@@ -54,7 +55,7 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons
// Get the synchronization context.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
- std::vector<KSynchronizationObject*> objs(num_handles);
+ std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;
// Copy user handles.
if (num_handles > 0) {
@@ -72,8 +73,8 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons
});
// Wait on the objects.
- Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(),
- static_cast<s32>(objs.size()), timeout_ns);
+ Result res =
+ KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout_ns);
R_SUCCEED_IF(res == ResultSessionClosed);
R_RETURN(res);
@@ -87,8 +88,7 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
// Ensure number of handles is valid.
R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
-
- std::vector<Handle> handles(num_handles);
+ std::array<Handle, Svc::ArgumentHandleCountMax> handles;
if (num_handles > 0) {
GetCurrentMemory(system.Kernel())
.ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 37b54079c..36b94e6bf 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -174,7 +174,7 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha
}
// Get the thread context.
- std::vector<u8> context;
+ static thread_local Common::ScratchBuffer<u8> context;
R_TRY(thread->GetThreadContext3(context));
// Copy the thread context to user space.
diff --git a/src/core/hle/kernel/svc/svc_tick.cpp b/src/core/hle/kernel/svc/svc_tick.cpp
index 561336482..7dd7c6e51 100644
--- a/src/core/hle/kernel/svc/svc_tick.cpp
+++ b/src/core/hle/kernel/svc/svc_tick.cpp
@@ -12,16 +12,8 @@ namespace Kernel::Svc {
int64_t GetSystemTick(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called");
- auto& core_timing = system.CoreTiming();
-
// Returns the value of cntpct_el0 (https://switchbrew.org/wiki/SVC#svcGetSystemTick)
- const u64 result{core_timing.GetClockTicks()};
-
- if (!system.Kernel().IsMulticore()) {
- core_timing.AddTicks(400U);
- }
-
- return static_cast<int64_t>(result);
+ return static_cast<int64_t>(system.CoreTiming().GetClockTicks());
}
int64_t GetSystemTick64(Core::System& system) {
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index 8b754e9d4..19ed184e8 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -141,7 +141,7 @@ void Cabinet::DisplayCompleted(bool apply_changes, std::string_view amiibo_name)
applet_output.device_handle = applet_input_common.device_handle;
applet_output.result = CabinetResult::Cancel;
const auto reg_result = nfp_device->GetRegisterInfo(applet_output.register_info);
- const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info, false);
+ const auto tag_result = nfp_device->GetTagInfo(applet_output.tag_info);
nfp_device->Finalize();
if (reg_result.IsSuccess()) {
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index f0640c64f..c8d574993 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -5,6 +5,7 @@
#include "audio_core/renderer/audio_device.h"
#include "common/common_funcs.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/kernel/k_event.h"
@@ -123,19 +124,13 @@ private:
void GetReleasedAudioInBuffer(HLERequestContext& ctx) {
const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>();
- std::vector<u64> released_buffers(write_buffer_size);
+ tmp_buffer.resize_destructive(write_buffer_size);
+ tmp_buffer[0] = 0;
- const auto count = impl->GetReleasedBuffers(released_buffers);
+ const auto count = impl->GetReleasedBuffers(tmp_buffer);
- [[maybe_unused]] std::string tags{};
- for (u32 i = 0; i < count; i++) {
- tags += fmt::format("{:08X}, ", released_buffers[i]);
- }
- [[maybe_unused]] auto sessionid{impl->GetSystem().GetSessionId()};
- LOG_TRACE(Service_Audio, "called. Session {} released {} buffers: {}", sessionid, count,
- tags);
+ ctx.WriteBuffer(tmp_buffer);
- ctx.WriteBuffer(released_buffers);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(count);
@@ -200,6 +195,7 @@ private:
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event;
std::shared_ptr<AudioCore::AudioIn::In> impl;
+ Common::ScratchBuffer<u64> tmp_buffer;
};
AudInU::AudInU(Core::System& system_)
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 3e62fa4fc..032c8c11f 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -123,19 +123,13 @@ private:
void GetReleasedAudioOutBuffers(HLERequestContext& ctx) {
const auto write_buffer_size = ctx.GetWriteBufferNumElements<u64>();
- std::vector<u64> released_buffers(write_buffer_size);
+ tmp_buffer.resize_destructive(write_buffer_size);
+ tmp_buffer[0] = 0;
- const auto count = impl->GetReleasedBuffers(released_buffers);
+ const auto count = impl->GetReleasedBuffers(tmp_buffer);
- [[maybe_unused]] std::string tags{};
- for (u32 i = 0; i < count; i++) {
- tags += fmt::format("{:08X}, ", released_buffers[i]);
- }
- [[maybe_unused]] const auto sessionid{impl->GetSystem().GetSessionId()};
- LOG_TRACE(Service_Audio, "called. Session {} released {} buffers: {}", sessionid, count,
- tags);
+ ctx.WriteBuffer(tmp_buffer);
- ctx.WriteBuffer(released_buffers);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(count);
@@ -211,6 +205,7 @@ private:
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* event;
std::shared_ptr<AudioCore::AudioOut::Out> impl;
+ Common::ScratchBuffer<u64> tmp_buffer;
};
AudOutU::AudOutU(Core::System& system_)
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 7086d4750..12845c23a 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -116,28 +116,26 @@ private:
// These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
// checking size 0. Performance size is 0 for most games.
- std::vector<u8> output{};
- std::vector<u8> performance{};
auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
if (is_buffer_b) {
const auto buffersB{ctx.BufferDescriptorB()};
- output.resize(buffersB[0].Size(), 0);
- performance.resize(buffersB[1].Size(), 0);
+ tmp_output.resize_destructive(buffersB[0].Size());
+ tmp_performance.resize_destructive(buffersB[1].Size());
} else {
const auto buffersC{ctx.BufferDescriptorC()};
- output.resize(buffersC[0].Size(), 0);
- performance.resize(buffersC[1].Size(), 0);
+ tmp_output.resize_destructive(buffersC[0].Size());
+ tmp_performance.resize_destructive(buffersC[1].Size());
}
- auto result = impl->RequestUpdate(input, performance, output);
+ auto result = impl->RequestUpdate(input, tmp_performance, tmp_output);
if (result.IsSuccess()) {
if (is_buffer_b) {
- ctx.WriteBufferB(output.data(), output.size(), 0);
- ctx.WriteBufferB(performance.data(), performance.size(), 1);
+ ctx.WriteBufferB(tmp_output.data(), tmp_output.size(), 0);
+ ctx.WriteBufferB(tmp_performance.data(), tmp_performance.size(), 1);
} else {
- ctx.WriteBufferC(output.data(), output.size(), 0);
- ctx.WriteBufferC(performance.data(), performance.size(), 1);
+ ctx.WriteBufferC(tmp_output.data(), tmp_output.size(), 0);
+ ctx.WriteBufferC(tmp_performance.data(), tmp_performance.size(), 1);
}
} else {
LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.description);
@@ -235,6 +233,8 @@ private:
Kernel::KEvent* rendered_event;
Manager& manager;
std::unique_ptr<Renderer> impl;
+ Common::ScratchBuffer<u8> tmp_output;
+ Common::ScratchBuffer<u8> tmp_performance;
};
class IAudioDevice final : public ServiceFramework<IAudioDevice> {
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index 24ce37e87..d8e9c8719 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -4,6 +4,7 @@
#pragma once
#include "audio_core/audio_render_manager.h"
+#include "common/scratch_buffer.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 451ac224a..c835f6cb7 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -68,13 +68,13 @@ private:
ExtraBehavior extra_behavior) {
u32 consumed = 0;
u32 sample_count = 0;
- std::vector<opus_int16> samples(ctx.GetWriteBufferNumElements<opus_int16>());
+ tmp_samples.resize_destructive(ctx.GetWriteBufferNumElements<opus_int16>());
if (extra_behavior == ExtraBehavior::ResetContext) {
ResetDecoderContext();
}
- if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), samples, performance)) {
+ if (!DecodeOpusData(consumed, sample_count, ctx.ReadBuffer(), tmp_samples, performance)) {
LOG_ERROR(Audio, "Failed to decode opus data");
IPC::ResponseBuilder rb{ctx, 2};
// TODO(ogniK): Use correct error code
@@ -90,11 +90,11 @@ private:
if (performance) {
rb.Push<u64>(*performance);
}
- ctx.WriteBuffer(samples);
+ ctx.WriteBuffer(tmp_samples);
}
bool DecodeOpusData(u32& consumed, u32& sample_count, std::span<const u8> input,
- std::vector<opus_int16>& output, u64* out_performance_time) const {
+ std::span<opus_int16> output, u64* out_performance_time) const {
const auto start_time = std::chrono::steady_clock::now();
const std::size_t raw_output_sz = output.size() * sizeof(opus_int16);
if (sizeof(OpusPacketHeader) > input.size()) {
@@ -154,6 +154,7 @@ private:
OpusDecoderPtr decoder;
u32 sample_rate;
u32 channel_count;
+ Common::ScratchBuffer<opus_int16> tmp_samples;
};
class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp
index 5604a6fda..80aac221b 100644
--- a/src/core/hle/service/hid/hidbus.cpp
+++ b/src/core/hle/service/hid/hidbus.cpp
@@ -5,7 +5,6 @@
#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
-#include "core/core_timing_util.h"
#include "core/hid/hid_types.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
index b2bcb68c3..bc232c334 100644
--- a/src/core/hle/service/nfc/common/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
@@ -36,12 +36,12 @@ bool IsAmiiboValid(const EncryptedNTAG215File& ntag_file) {
// Validate UUID
constexpr u8 CT = 0x88; // As defined in `ISO / IEC 14443 - 3`
- if ((CT ^ ntag_file.uuid.uid[0] ^ ntag_file.uuid.uid[1] ^ ntag_file.uuid.uid[2]) !=
- ntag_file.uuid.uid[3]) {
+ if ((CT ^ ntag_file.uuid.part1[0] ^ ntag_file.uuid.part1[1] ^ ntag_file.uuid.part1[2]) !=
+ ntag_file.uuid.crc_check1) {
return false;
}
- if ((ntag_file.uuid.uid[4] ^ ntag_file.uuid.uid[5] ^ ntag_file.uuid.uid[6] ^
- ntag_file.uuid.nintendo_id) != ntag_file.uuid.lock_bytes[0]) {
+ if ((ntag_file.uuid.part2[0] ^ ntag_file.uuid.part2[1] ^ ntag_file.uuid.part2[2] ^
+ ntag_file.uuid.nintendo_id) != ntag_file.uuid_crc_check2) {
return false;
}
@@ -74,8 +74,9 @@ bool IsAmiiboValid(const NTAG215File& ntag_file) {
NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
NTAG215File encoded_data{};
- encoded_data.uid = nfc_data.uuid.uid;
- encoded_data.nintendo_id = nfc_data.uuid.nintendo_id;
+ encoded_data.uid = nfc_data.uuid;
+ encoded_data.uid_crc_check2 = nfc_data.uuid_crc_check2;
+ encoded_data.internal_number = nfc_data.internal_number;
encoded_data.static_lock = nfc_data.static_lock;
encoded_data.compability_container = nfc_data.compability_container;
encoded_data.hmac_data = nfc_data.user_memory.hmac_data;
@@ -94,7 +95,6 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
encoded_data.register_info_crc = nfc_data.user_memory.register_info_crc;
encoded_data.application_area = nfc_data.user_memory.application_area;
encoded_data.hmac_tag = nfc_data.user_memory.hmac_tag;
- encoded_data.lock_bytes = nfc_data.uuid.lock_bytes;
encoded_data.model_info = nfc_data.user_memory.model_info;
encoded_data.keygen_salt = nfc_data.user_memory.keygen_salt;
encoded_data.dynamic_lock = nfc_data.dynamic_lock;
@@ -108,9 +108,9 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data) {
EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) {
EncryptedNTAG215File nfc_data{};
- nfc_data.uuid.uid = encoded_data.uid;
- nfc_data.uuid.nintendo_id = encoded_data.nintendo_id;
- nfc_data.uuid.lock_bytes = encoded_data.lock_bytes;
+ nfc_data.uuid = encoded_data.uid;
+ nfc_data.uuid_crc_check2 = encoded_data.uid_crc_check2;
+ nfc_data.internal_number = encoded_data.internal_number;
nfc_data.static_lock = encoded_data.static_lock;
nfc_data.compability_container = encoded_data.compability_container;
nfc_data.user_memory.hmac_data = encoded_data.hmac_data;
@@ -139,23 +139,12 @@ EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data) {
return nfc_data;
}
-u32 GetTagPassword(const TagUuid& uuid) {
- // Verify that the generated password is correct
- u32 password = 0xAA ^ (uuid.uid[1] ^ uuid.uid[3]);
- password &= (0x55 ^ (uuid.uid[2] ^ uuid.uid[4])) << 8;
- password &= (0xAA ^ (uuid.uid[3] ^ uuid.uid[5])) << 16;
- password &= (0x55 ^ (uuid.uid[4] ^ uuid.uid[6])) << 24;
- return password;
-}
-
HashSeed GetSeed(const NTAG215File& data) {
HashSeed seed{
.magic = data.write_counter,
.padding = {},
.uid_1 = data.uid,
- .nintendo_id_1 = data.nintendo_id,
.uid_2 = data.uid,
- .nintendo_id_2 = data.nintendo_id,
.keygen_salt = data.keygen_salt,
};
@@ -177,10 +166,11 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
output.insert(output.end(), key.magic_bytes.begin(),
key.magic_bytes.begin() + key.magic_length);
- output.insert(output.end(), seed.uid_1.begin(), seed.uid_1.end());
- output.emplace_back(seed.nintendo_id_1);
- output.insert(output.end(), seed.uid_2.begin(), seed.uid_2.end());
- output.emplace_back(seed.nintendo_id_2);
+ std::array<u8, sizeof(NFP::TagUuid)> seed_uuid{};
+ memcpy(seed_uuid.data(), &seed.uid_1, sizeof(NFP::TagUuid));
+ output.insert(output.end(), seed_uuid.begin(), seed_uuid.end());
+ memcpy(seed_uuid.data(), &seed.uid_2, sizeof(NFP::TagUuid));
+ output.insert(output.end(), seed_uuid.begin(), seed_uuid.end());
for (std::size_t i = 0; i < sizeof(seed.keygen_salt); i++) {
output.emplace_back(static_cast<u8>(seed.keygen_salt[i] ^ key.xor_pad[i]));
@@ -264,8 +254,8 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou
// Copy the rest of the data directly
out_data.uid = in_data.uid;
- out_data.nintendo_id = in_data.nintendo_id;
- out_data.lock_bytes = in_data.lock_bytes;
+ out_data.uid_crc_check2 = in_data.uid_crc_check2;
+ out_data.internal_number = in_data.internal_number;
out_data.static_lock = in_data.static_lock;
out_data.compability_container = in_data.compability_container;
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h
index bf3044ed9..6a3e0841e 100644
--- a/src/core/hle/service/nfc/common/amiibo_crypto.h
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.h
@@ -24,10 +24,8 @@ using DrgbOutput = std::array<u8, 0x20>;
struct HashSeed {
u16_be magic;
std::array<u8, 0xE> padding;
- NFC::UniqueSerialNumber uid_1;
- u8 nintendo_id_1;
- NFC::UniqueSerialNumber uid_2;
- u8 nintendo_id_2;
+ TagUuid uid_1;
+ TagUuid uid_2;
std::array<u8, 0x20> keygen_salt;
};
static_assert(sizeof(HashSeed) == 0x40, "HashSeed is an invalid size");
@@ -69,9 +67,6 @@ NTAG215File NfcDataToEncodedData(const EncryptedNTAG215File& nfc_data);
/// Converts from encoded file format to encrypted file format
EncryptedNTAG215File EncodedDataToNfcData(const NTAG215File& encoded_data);
-/// Returns password needed to allow write access to protected memory
-u32 GetTagPassword(const TagUuid& uuid);
-
// Generates Seed needed for key derivation
HashSeed GetSeed(const NTAG215File& data);
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index b14f682b5..5bf289818 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -93,7 +93,8 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
const auto nfc_status = npad_device->GetNfc();
switch (nfc_status.state) {
case Common::Input::NfcState::NewAmiibo:
- LoadNfcTag(nfc_status.data);
+ LoadNfcTag(nfc_status.protocol, nfc_status.tag_type, nfc_status.uuid_length,
+ nfc_status.uuid);
break;
case Common::Input::NfcState::AmiiboRemoved:
if (device_state == DeviceState::Initialized || device_state == DeviceState::TagRemoved) {
@@ -108,28 +109,46 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
}
}
-bool NfcDevice::LoadNfcTag(std::span<const u8> data) {
+bool NfcDevice::LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid) {
if (device_state != DeviceState::SearchingForTag) {
LOG_ERROR(Service_NFC, "Game is not looking for nfc tag, current state {}", device_state);
return false;
}
+ if ((protocol & static_cast<u8>(allowed_protocols)) == 0) {
+ LOG_ERROR(Service_NFC, "Protocol not supported {}", protocol);
+ return false;
+ }
+
+ real_tag_info = {
+ .uuid = uuid,
+ .uuid_length = uuid_length,
+ .protocol = static_cast<NfcProtocol>(protocol),
+ .tag_type = static_cast<TagType>(tag_type),
+ };
+
+ device_state = DeviceState::TagFound;
+ deactivate_event->GetReadableEvent().Clear();
+ activate_event->Signal();
+ return true;
+}
+
+bool NfcDevice::LoadAmiiboData() {
+ std::vector<u8> data{};
+
+ if (!npad_device->ReadAmiiboData(data)) {
+ return false;
+ }
+
if (data.size() < sizeof(NFP::EncryptedNTAG215File)) {
LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size());
return false;
}
- mifare_data.resize(data.size());
- memcpy(mifare_data.data(), data.data(), data.size());
-
memcpy(&tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
is_plain_amiibo = NFP::AmiiboCrypto::IsAmiiboValid(tag_data);
is_write_protected = false;
- device_state = DeviceState::TagFound;
- deactivate_event->GetReadableEvent().Clear();
- activate_event->Signal();
-
// Fallback for plain amiibos
if (is_plain_amiibo) {
LOG_INFO(Service_NFP, "Using plain amiibo");
@@ -147,6 +166,7 @@ bool NfcDevice::LoadNfcTag(std::span<const u8> data) {
return true;
}
+ LOG_INFO(Service_NFP, "Using encrypted amiibo");
tag_data = {};
memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File));
return true;
@@ -162,7 +182,6 @@ void NfcDevice::CloseNfcTag() {
device_state = DeviceState::TagRemoved;
encrypted_tag_data = {};
tag_data = {};
- mifare_data = {};
activate_event->GetReadableEvent().Clear();
deactivate_event->Signal();
}
@@ -179,8 +198,12 @@ void NfcDevice::Initialize() {
device_state = npad_device->HasNfc() ? DeviceState::Initialized : DeviceState::Unavailable;
encrypted_tag_data = {};
tag_data = {};
- mifare_data = {};
- is_initalized = true;
+
+ if (device_state != DeviceState::Initialized) {
+ return;
+ }
+
+ is_initalized = npad_device->AddNfcHandle();
}
void NfcDevice::Finalize() {
@@ -190,6 +213,11 @@ void NfcDevice::Finalize() {
if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {
StopDetection();
}
+
+ if (device_state != DeviceState::Unavailable) {
+ npad_device->RemoveNfcHandle();
+ }
+
device_state = DeviceState::Unavailable;
is_initalized = false;
}
@@ -200,10 +228,8 @@ Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {
return ResultWrongDeviceState;
}
- if (npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
- Common::Input::PollingMode::NFC) !=
- Common::Input::DriverResult::Success) {
- LOG_ERROR(Service_NFC, "Nfc not supported");
+ if (!npad_device->StartNfcPolling()) {
+ LOG_ERROR(Service_NFC, "Nfc polling not supported");
return ResultNfcDisabled;
}
@@ -213,9 +239,6 @@ Result NfcDevice::StartDetection(NfcProtocol allowed_protocol) {
}
Result NfcDevice::StopDetection() {
- npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
- Common::Input::PollingMode::Active);
-
if (device_state == DeviceState::Initialized) {
return ResultSuccess;
}
@@ -225,6 +248,7 @@ Result NfcDevice::StopDetection() {
}
if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {
+ npad_device->StopNfcPolling();
device_state = DeviceState::Initialized;
return ResultSuccess;
}
@@ -233,7 +257,7 @@ Result NfcDevice::StopDetection() {
return ResultWrongDeviceState;
}
-Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
+Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const {
if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
if (device_state == DeviceState::TagRemoved) {
@@ -242,72 +266,78 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
return ResultWrongDeviceState;
}
- UniqueSerialNumber uuid = encrypted_tag_data.uuid.uid;
+ tag_info = real_tag_info;
// Generate random UUID to bypass amiibo load limits
- if (Settings::values.random_amiibo_id) {
+ if (real_tag_info.tag_type == TagType::Type2 && Settings::values.random_amiibo_id) {
Common::TinyMT rng{};
rng.Initialize(static_cast<u32>(GetCurrentPosixTime()));
- rng.GenerateRandomBytes(uuid.data(), sizeof(UniqueSerialNumber));
- uuid[3] = 0x88 ^ uuid[0] ^ uuid[1] ^ uuid[2];
+ rng.GenerateRandomBytes(tag_info.uuid.data(), tag_info.uuid_length);
}
- if (is_mifare) {
- tag_info = {
- .uuid = uuid,
- .uuid_extension = {},
- .uuid_length = static_cast<u8>(uuid.size()),
- .protocol = NfcProtocol::TypeA,
- .tag_type = TagType::Type4,
- };
- return ResultSuccess;
- }
-
- // Protocol and tag type may change here
- tag_info = {
- .uuid = uuid,
- .uuid_extension = {},
- .uuid_length = static_cast<u8>(uuid.size()),
- .protocol = NfcProtocol::TypeA,
- .tag_type = TagType::Type2,
- };
-
return ResultSuccess;
}
Result NfcDevice::ReadMifare(std::span<const MifareReadBlockParameter> parameters,
std::span<MifareReadBlockData> read_block_data) const {
+ if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
+ LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
+ if (device_state == DeviceState::TagRemoved) {
+ return ResultTagRemoved;
+ }
+ return ResultWrongDeviceState;
+ }
+
Result result = ResultSuccess;
- for (std::size_t i = 0; i < parameters.size(); i++) {
- result = ReadMifare(parameters[i], read_block_data[i]);
- if (result.IsError()) {
- break;
- }
+ TagInfo tag_info{};
+ result = GetTagInfo(tag_info);
+
+ if (result.IsError()) {
+ return result;
}
- return result;
-}
+ if (tag_info.protocol != NfcProtocol::TypeA || tag_info.tag_type != TagType::Mifare) {
+ return ResultInvalidTagType;
+ }
-Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter,
- MifareReadBlockData& read_block_data) const {
- const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock);
- read_block_data.sector_number = parameter.sector_number;
+ if (parameters.size() == 0) {
+ return ResultInvalidArgument;
+ }
- if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return ResultTagRemoved;
+ Common::Input::MifareRequest request{};
+ Common::Input::MifareRequest out_data{};
+ const auto unknown = parameters[0].sector_key.unknown;
+ for (std::size_t i = 0; i < parameters.size(); i++) {
+ if (unknown != parameters[i].sector_key.unknown) {
+ return ResultInvalidArgument;
}
- return ResultWrongDeviceState;
}
- if (mifare_data.size() < sector_index + sizeof(DataBlock)) {
- return Mifare::ResultReadError;
+ for (std::size_t i = 0; i < parameters.size(); i++) {
+ if (parameters[i].sector_key.command == MifareCmd::None) {
+ continue;
+ }
+ request.data[i].command = static_cast<u8>(parameters[i].sector_key.command);
+ request.data[i].sector = parameters[i].sector_number;
+ memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(),
+ sizeof(KeyData));
}
- // TODO: Use parameter.sector_key to read encrypted data
- memcpy(read_block_data.data.data(), mifare_data.data() + sector_index, sizeof(DataBlock));
+ if (!npad_device->ReadMifareData(request, out_data)) {
+ return ResultMifareError288;
+ }
+
+ for (std::size_t i = 0; i < read_block_data.size(); i++) {
+ if (static_cast<MifareCmd>(out_data.data[i].command) == MifareCmd::None) {
+ continue;
+ }
+
+ read_block_data[i] = {
+ .data = out_data.data[i].data,
+ .sector_number = out_data.data[i].sector,
+ };
+ }
return ResultSuccess;
}
@@ -315,40 +345,45 @@ Result NfcDevice::ReadMifare(const MifareReadBlockParameter& parameter,
Result NfcDevice::WriteMifare(std::span<const MifareWriteBlockParameter> parameters) {
Result result = ResultSuccess;
- for (std::size_t i = 0; i < parameters.size(); i++) {
- result = WriteMifare(parameters[i]);
- if (result.IsError()) {
- break;
- }
- }
+ TagInfo tag_info{};
+ result = GetTagInfo(tag_info);
- if (!npad_device->WriteNfc(mifare_data)) {
- LOG_ERROR(Service_NFP, "Error writing to file");
- return Mifare::ResultReadError;
+ if (result.IsError()) {
+ return result;
}
- return result;
-}
+ if (tag_info.protocol != NfcProtocol::TypeA || tag_info.tag_type != TagType::Mifare) {
+ return ResultInvalidTagType;
+ }
-Result NfcDevice::WriteMifare(const MifareWriteBlockParameter& parameter) {
- const std::size_t sector_index = parameter.sector_number * sizeof(DataBlock);
+ if (parameters.size() == 0) {
+ return ResultInvalidArgument;
+ }
- if (device_state != DeviceState::TagFound && device_state != DeviceState::TagMounted) {
- LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
- if (device_state == DeviceState::TagRemoved) {
- return ResultTagRemoved;
+ const auto unknown = parameters[0].sector_key.unknown;
+ for (std::size_t i = 0; i < parameters.size(); i++) {
+ if (unknown != parameters[i].sector_key.unknown) {
+ return ResultInvalidArgument;
}
- return ResultWrongDeviceState;
}
- if (mifare_data.size() < sector_index + sizeof(DataBlock)) {
- return Mifare::ResultReadError;
+ Common::Input::MifareRequest request{};
+ for (std::size_t i = 0; i < parameters.size(); i++) {
+ if (parameters[i].sector_key.command == MifareCmd::None) {
+ continue;
+ }
+ request.data[i].command = static_cast<u8>(parameters[i].sector_key.command);
+ request.data[i].sector = parameters[i].sector_number;
+ memcpy(request.data[i].key.data(), parameters[i].sector_key.sector_key.data(),
+ sizeof(KeyData));
+ memcpy(request.data[i].data.data(), parameters[i].data.data(), sizeof(KeyData));
}
- // TODO: Use parameter.sector_key to encrypt the data
- memcpy(mifare_data.data() + sector_index, parameter.data.data(), sizeof(DataBlock));
+ if (!npad_device->WriteMifareData(request)) {
+ return ResultMifareError288;
+ }
- return ResultSuccess;
+ return result;
}
Result NfcDevice::SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
@@ -364,9 +399,14 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target
return ResultWrongDeviceState;
}
+ if (!LoadAmiiboData()) {
+ LOG_ERROR(Service_NFP, "Not an amiibo");
+ return ResultInvalidTagType;
+ }
+
if (!NFP::AmiiboCrypto::IsAmiiboValid(encrypted_tag_data)) {
LOG_ERROR(Service_NFP, "Not an amiibo");
- return ResultNotAnAmiibo;
+ return ResultInvalidTagType;
}
// The loaded amiibo is not encrypted
@@ -381,14 +421,14 @@ Result NfcDevice::Mount(NFP::ModelType model_type, NFP::MountTarget mount_target
}
if (!NFP::AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) {
- bool has_backup = HasBackup(encrypted_tag_data.uuid.uid).IsSuccess();
+ bool has_backup = HasBackup(encrypted_tag_data.uuid).IsSuccess();
LOG_ERROR(Service_NFP, "Can't decode amiibo, has_backup= {}", has_backup);
return has_backup ? ResultCorruptedDataWithBackup : ResultCorruptedData;
}
std::vector<u8> data(sizeof(NFP::EncryptedNTAG215File));
memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
- WriteBackupData(encrypted_tag_data.uuid.uid, data);
+ WriteBackupData(encrypted_tag_data.uuid, data);
device_state = DeviceState::TagMounted;
mount_target = mount_target_;
@@ -492,7 +532,7 @@ Result NfcDevice::FlushWithBreak(NFP::BreakType break_type) {
}
memcpy(data.data(), &encrypted_tag_data, sizeof(encrypted_tag_data));
- WriteBackupData(encrypted_tag_data.uuid.uid, data);
+ WriteBackupData(encrypted_tag_data.uuid, data);
}
if (!npad_device->WriteNfc(data)) {
@@ -514,13 +554,13 @@ Result NfcDevice::Restore() {
NFC::TagInfo tag_info{};
std::array<u8, sizeof(NFP::EncryptedNTAG215File)> data{};
- Result result = GetTagInfo(tag_info, false);
+ Result result = GetTagInfo(tag_info);
if (result.IsError()) {
return result;
}
- result = ReadBackupData(tag_info.uuid, data);
+ result = ReadBackupData(tag_info.uuid, tag_info.uuid_length, data);
if (result.IsError()) {
return result;
@@ -548,7 +588,7 @@ Result NfcDevice::Restore() {
}
if (!NFP::AmiiboCrypto::IsAmiiboValid(temporary_encrypted_tag_data)) {
- return ResultNotAnAmiibo;
+ return ResultInvalidTagType;
}
if (!is_plain_amiibo) {
@@ -587,7 +627,7 @@ Result NfcDevice::GetCommonInfo(NFP::CommonInfo& common_info) const {
// TODO: Validate this data
common_info = {
.last_write_date = settings.write_date.GetWriteDate(),
- .write_counter = tag_data.write_counter,
+ .write_counter = tag_data.application_write_counter,
.version = tag_data.amiibo_version,
.application_area_size = sizeof(NFP::ApplicationArea),
};
@@ -1194,10 +1234,12 @@ Result NfcDevice::BreakTag(NFP::BreakType break_type) {
return FlushWithBreak(break_type);
}
-Result NfcDevice::HasBackup(const NFC::UniqueSerialNumber& uid) const {
+Result NfcDevice::HasBackup(const UniqueSerialNumber& uid, std::size_t uuid_size) const {
+ ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size");
constexpr auto backup_dir = "backup";
const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir);
- const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, ""));
+ const auto file_name =
+ fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, ""));
if (!Common::FS::Exists(yuzu_amiibo_dir / backup_dir / file_name)) {
return ResultUnableToAccessBackupFile;
@@ -1206,10 +1248,19 @@ Result NfcDevice::HasBackup(const NFC::UniqueSerialNumber& uid) const {
return ResultSuccess;
}
-Result NfcDevice::ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u8> data) const {
+Result NfcDevice::HasBackup(const NFP::TagUuid& tag_uid) const {
+ UniqueSerialNumber uuid{};
+ memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid));
+ return HasBackup(uuid, sizeof(NFP::TagUuid));
+}
+
+Result NfcDevice::ReadBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size,
+ std::span<u8> data) const {
+ ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size");
constexpr auto backup_dir = "backup";
const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir);
- const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, ""));
+ const auto file_name =
+ fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, ""));
const Common::FS::IOFile keys_file{yuzu_amiibo_dir / backup_dir / file_name,
Common::FS::FileAccessMode::Read,
@@ -1228,12 +1279,21 @@ Result NfcDevice::ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u
return ResultSuccess;
}
-Result NfcDevice::WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span<const u8> data) {
+Result NfcDevice::ReadBackupData(const NFP::TagUuid& tag_uid, std::span<u8> data) const {
+ UniqueSerialNumber uuid{};
+ memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid));
+ return ReadBackupData(uuid, sizeof(NFP::TagUuid), data);
+}
+
+Result NfcDevice::WriteBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size,
+ std::span<const u8> data) {
+ ASSERT_MSG(uuid_size < sizeof(UniqueSerialNumber), "Invalid UUID size");
constexpr auto backup_dir = "backup";
const auto yuzu_amiibo_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::AmiiboDir);
- const auto file_name = fmt::format("{0:02x}.bin", fmt::join(uid, ""));
+ const auto file_name =
+ fmt::format("{0:02x}.bin", fmt::join(uid.begin(), uid.begin() + uuid_size, ""));
- if (HasBackup(uid).IsError()) {
+ if (HasBackup(uid, uuid_size).IsError()) {
if (!Common::FS::CreateDir(yuzu_amiibo_dir / backup_dir)) {
return ResultBackupPathAlreadyExist;
}
@@ -1260,6 +1320,12 @@ Result NfcDevice::WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span<
return ResultSuccess;
}
+Result NfcDevice::WriteBackupData(const NFP::TagUuid& tag_uid, std::span<const u8> data) {
+ UniqueSerialNumber uuid{};
+ memcpy(uuid.data(), &tag_uid, sizeof(NFP::TagUuid));
+ return WriteBackupData(uuid, sizeof(NFP::TagUuid), data);
+}
+
Result NfcDevice::WriteNtf(std::span<const u8> data) {
if (device_state != DeviceState::TagMounted) {
LOG_ERROR(Service_NFC, "Wrong device state {}", device_state);
diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h
index 6f049b687..0ed1ff34c 100644
--- a/src/core/hle/service/nfc/common/device.h
+++ b/src/core/hle/service/nfc/common/device.h
@@ -42,15 +42,12 @@ public:
Result StartDetection(NfcProtocol allowed_protocol);
Result StopDetection();
- Result GetTagInfo(TagInfo& tag_info, bool is_mifare) const;
+ Result GetTagInfo(TagInfo& tag_info) const;
Result ReadMifare(std::span<const MifareReadBlockParameter> parameters,
std::span<MifareReadBlockData> read_block_data) const;
- Result ReadMifare(const MifareReadBlockParameter& parameter,
- MifareReadBlockData& read_block_data) const;
Result WriteMifare(std::span<const MifareWriteBlockParameter> parameters);
- Result WriteMifare(const MifareWriteBlockParameter& parameter);
Result SendCommandByPassThrough(const Time::Clock::TimeSpanType& timeout,
std::span<const u8> command_data, std::span<u8> out_data);
@@ -86,9 +83,14 @@ public:
Result GetAll(NFP::NfpData& data) const;
Result SetAll(const NFP::NfpData& data);
Result BreakTag(NFP::BreakType break_type);
- Result HasBackup(const NFC::UniqueSerialNumber& uid) const;
- Result ReadBackupData(const NFC::UniqueSerialNumber& uid, std::span<u8> data) const;
- Result WriteBackupData(const NFC::UniqueSerialNumber& uid, std::span<const u8> data);
+ Result HasBackup(const UniqueSerialNumber& uid, std::size_t uuid_size) const;
+ Result HasBackup(const NFP::TagUuid& tag_uid) const;
+ Result ReadBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size,
+ std::span<u8> data) const;
+ Result ReadBackupData(const NFP::TagUuid& tag_uid, std::span<u8> data) const;
+ Result WriteBackupData(const UniqueSerialNumber& uid, std::size_t uuid_size,
+ std::span<const u8> data);
+ Result WriteBackupData(const NFP::TagUuid& tag_uid, std::span<const u8> data);
Result WriteNtf(std::span<const u8> data);
u64 GetHandle() const;
@@ -100,7 +102,8 @@ public:
private:
void NpadUpdate(Core::HID::ControllerTriggerType type);
- bool LoadNfcTag(std::span<const u8> data);
+ bool LoadNfcTag(u8 protocol, u8 tag_type, u8 uuid_length, UniqueSerialNumber uuid);
+ bool LoadAmiiboData();
void CloseNfcTag();
NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const;
@@ -135,8 +138,8 @@ private:
bool is_write_protected{};
NFP::MountTarget mount_target{NFP::MountTarget::None};
+ TagInfo real_tag_info{};
NFP::NTAG215File tag_data{};
- std::vector<u8> mifare_data{};
NFP::EncryptedNTAG215File encrypted_tag_data{};
};
diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp
index cffd602df..562f3a28e 100644
--- a/src/core/hle/service/nfc/common/device_manager.cpp
+++ b/src/core/hle/service/nfc/common/device_manager.cpp
@@ -29,6 +29,9 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex
}
DeviceManager ::~DeviceManager() {
+ if (is_initialized) {
+ Finalize();
+ }
service_context.CloseEvent(availability_change_event);
}
@@ -125,14 +128,14 @@ Result DeviceManager::StopDetection(u64 device_handle) {
return result;
}
-Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info, bool is_mifare) const {
+Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const {
std::scoped_lock lock{mutex};
std::shared_ptr<NfcDevice> device = nullptr;
auto result = GetDeviceHandle(device_handle, device);
if (result.IsSuccess()) {
- result = device->GetTagInfo(tag_info, is_mifare);
+ result = device->GetTagInfo(tag_info);
result = VerifyDeviceResult(device, result);
}
@@ -546,11 +549,11 @@ Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) cons
NFC::TagInfo tag_info{};
if (result.IsSuccess()) {
- result = device->GetTagInfo(tag_info, false);
+ result = device->GetTagInfo(tag_info);
}
if (result.IsSuccess()) {
- result = device->ReadBackupData(tag_info.uuid, data);
+ result = device->ReadBackupData(tag_info.uuid, tag_info.uuid_length, data);
result = VerifyDeviceResult(device, result);
}
@@ -565,11 +568,11 @@ Result DeviceManager::WriteBackupData(u64 device_handle, std::span<const u8> dat
NFC::TagInfo tag_info{};
if (result.IsSuccess()) {
- result = device->GetTagInfo(tag_info, false);
+ result = device->GetTagInfo(tag_info);
}
if (result.IsSuccess()) {
- result = device->WriteBackupData(tag_info.uuid, data);
+ result = device->WriteBackupData(tag_info.uuid, tag_info.uuid_length, data);
result = VerifyDeviceResult(device, result);
}
diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h
index 2971e280f..c61ba0cf3 100644
--- a/src/core/hle/service/nfc/common/device_manager.h
+++ b/src/core/hle/service/nfc/common/device_manager.h
@@ -33,7 +33,7 @@ public:
Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;
Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);
Result StopDetection(u64 device_handle);
- Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info, bool is_mifare) const;
+ Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info) const;
Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const;
Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const;
Result ReadMifare(u64 device_handle,
diff --git a/src/core/hle/service/nfc/mifare_result.h b/src/core/hle/service/nfc/mifare_result.h
index 4b60048a5..16a9171e6 100644
--- a/src/core/hle/service/nfc/mifare_result.h
+++ b/src/core/hle/service/nfc/mifare_result.h
@@ -12,6 +12,6 @@ constexpr Result ResultInvalidArgument(ErrorModule::NFCMifare, 65);
constexpr Result ResultWrongDeviceState(ErrorModule::NFCMifare, 73);
constexpr Result ResultNfcDisabled(ErrorModule::NFCMifare, 80);
constexpr Result ResultTagRemoved(ErrorModule::NFCMifare, 97);
-constexpr Result ResultReadError(ErrorModule::NFCMifare, 288);
+constexpr Result ResultNotAMifare(ErrorModule::NFCMifare, 288);
} // namespace Service::NFC::Mifare
diff --git a/src/core/hle/service/nfc/mifare_types.h b/src/core/hle/service/nfc/mifare_types.h
index 75b59f021..467937399 100644
--- a/src/core/hle/service/nfc/mifare_types.h
+++ b/src/core/hle/service/nfc/mifare_types.h
@@ -11,9 +11,10 @@
namespace Service::NFC {
enum class MifareCmd : u8 {
+ None = 0x00,
+ Read = 0x30,
AuthA = 0x60,
AuthB = 0x61,
- Read = 0x30,
Write = 0xA0,
Transfer = 0xB0,
Decrement = 0xC0,
@@ -35,17 +36,17 @@ static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size");
// This is nn::nfc::MifareReadBlockParameter
struct MifareReadBlockParameter {
- u8 sector_number;
+ u8 sector_number{};
INSERT_PADDING_BYTES(0x7);
- SectorKey sector_key;
+ SectorKey sector_key{};
};
static_assert(sizeof(MifareReadBlockParameter) == 0x18,
"MifareReadBlockParameter is an invalid size");
// This is nn::nfc::MifareReadBlockData
struct MifareReadBlockData {
- DataBlock data;
- u8 sector_number;
+ DataBlock data{};
+ u8 sector_number{};
INSERT_PADDING_BYTES(0x7);
};
static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size");
diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp
index 198d0f2b9..e7ca7582e 100644
--- a/src/core/hle/service/nfc/nfc_interface.cpp
+++ b/src/core/hle/service/nfc/nfc_interface.cpp
@@ -142,9 +142,13 @@ void NfcInterface::AttachAvailabilityChangeEvent(HLERequestContext& ctx) {
void NfcInterface::StartDetection(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto device_handle{rp.Pop<u64>()};
- const auto tag_protocol{rp.PopEnum<NfcProtocol>()};
- LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol);
+ auto tag_protocol{NfcProtocol::All};
+
+ if (backend_type == BackendType::Nfc) {
+ tag_protocol = rp.PopEnum<NfcProtocol>();
+ }
+ LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, tag_protocol);
auto result = GetManager()->StartDetection(device_handle, tag_protocol);
result = TranslateResultToServiceError(result);
@@ -170,8 +174,7 @@ void NfcInterface::GetTagInfo(HLERequestContext& ctx) {
LOG_INFO(Service_NFC, "called, device_handle={}", device_handle);
TagInfo tag_info{};
- auto result =
- GetManager()->GetTagInfo(device_handle, tag_info, backend_type == BackendType::Mifare);
+ auto result = GetManager()->GetTagInfo(device_handle, tag_info);
result = TranslateResultToServiceError(result);
if (result.IsSuccess()) {
@@ -212,8 +215,8 @@ void NfcInterface::ReadMifare(HLERequestContext& ctx) {
memcpy(read_commands.data(), buffer.data(),
number_of_commands * sizeof(MifareReadBlockParameter));
- LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}",
- device_handle, number_of_commands);
+ LOG_INFO(Service_NFC, "called, device_handle={}, read_commands_size={}", device_handle,
+ number_of_commands);
std::vector<MifareReadBlockData> out_data(number_of_commands);
auto result = GetManager()->ReadMifare(device_handle, read_commands, out_data);
@@ -355,7 +358,7 @@ Result NfcInterface::TranslateResultToNfp(Result result) const {
if (result == ResultApplicationAreaExist) {
return NFP::ResultApplicationAreaExist;
}
- if (result == ResultNotAnAmiibo) {
+ if (result == ResultInvalidTagType) {
return NFP::ResultNotAnAmiibo;
}
if (result == ResultUnableToAccessBackupFile) {
@@ -381,6 +384,9 @@ Result NfcInterface::TranslateResultToMifare(Result result) const {
if (result == ResultTagRemoved) {
return Mifare::ResultTagRemoved;
}
+ if (result == ResultInvalidTagType) {
+ return Mifare::ResultNotAMifare;
+ }
LOG_WARNING(Service_NFC, "Result conversion not handled");
return result;
}
diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h
index 59a808740..715c0e80c 100644
--- a/src/core/hle/service/nfc/nfc_result.h
+++ b/src/core/hle/service/nfc/nfc_result.h
@@ -24,7 +24,8 @@ constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136);
constexpr Result ResultCorruptedData(ErrorModule::NFC, 144);
constexpr Result ResultWrongApplicationAreaId(ErrorModule::NFC, 152);
constexpr Result ResultApplicationAreaExist(ErrorModule::NFC, 168);
-constexpr Result ResultNotAnAmiibo(ErrorModule::NFC, 178);
+constexpr Result ResultInvalidTagType(ErrorModule::NFC, 178);
constexpr Result ResultBackupPathAlreadyExist(ErrorModule::NFC, 216);
+constexpr Result ResultMifareError288(ErrorModule::NFC, 288);
} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc_types.h b/src/core/hle/service/nfc/nfc_types.h
index c7ebd1fdb..68e724442 100644
--- a/src/core/hle/service/nfc/nfc_types.h
+++ b/src/core/hle/service/nfc/nfc_types.h
@@ -35,32 +35,35 @@ enum class State : u32 {
// This is nn::nfc::TagType
enum class TagType : u32 {
- None,
- Type1, // ISO14443A RW 96-2k bytes 106kbit/s
- Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
- Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s
- Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
- Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
+ None = 0,
+ Type1 = 1U << 0, // ISO14443A RW. Topaz
+ Type2 = 1U << 1, // ISO14443A RW. Ultralight, NTAGX, ST25TN
+ Type3 = 1U << 2, // ISO14443A RW/RO. Sony FeliCa
+ Type4A = 1U << 3, // ISO14443A RW/RO. DESFire
+ Type4B = 1U << 4, // ISO14443B RW/RO. DESFire
+ Type5 = 1U << 5, // ISO15693 RW/RO. SLI, SLIX, ST25TV
+ Mifare = 1U << 6, // Mifare classic. Skylanders
+ All = 0xFFFFFFFF,
};
enum class PackedTagType : u8 {
- None,
- Type1, // ISO14443A RW 96-2k bytes 106kbit/s
- Type2, // ISO14443A RW/RO 540 bytes 106kbit/s
- Type3, // Sony FeliCa RW/RO 2k bytes 212kbit/s
- Type4, // ISO14443A RW/RO 4k-32k bytes 424kbit/s
- Type5, // ISO15693 RW/RO 540 bytes 106kbit/s
+ None = 0,
+ Type1 = 1U << 0, // ISO14443A RW. Topaz
+ Type2 = 1U << 1, // ISO14443A RW. Ultralight, NTAGX, ST25TN
+ Type3 = 1U << 2, // ISO14443A RW/RO. Sony FeliCa
+ Type4A = 1U << 3, // ISO14443A RW/RO. DESFire
+ Type4B = 1U << 4, // ISO14443B RW/RO. DESFire
+ Type5 = 1U << 5, // ISO15693 RW/RO. SLI, SLIX, ST25TV
+ Mifare = 1U << 6, // Mifare classic. Skylanders
+ All = 0xFF,
};
// This is nn::nfc::NfcProtocol
-// Verify this enum. It might be completely wrong default protocol is 0x48
enum class NfcProtocol : u32 {
None,
TypeA = 1U << 0, // ISO14443A
TypeB = 1U << 1, // ISO14443B
TypeF = 1U << 2, // Sony FeliCa
- Unknown1 = 1U << 3,
- Unknown2 = 1U << 5,
All = 0xFFFFFFFFU,
};
@@ -69,8 +72,7 @@ enum class TestWaveType : u32 {
Unknown,
};
-using UniqueSerialNumber = std::array<u8, 7>;
-using UniqueSerialNumberExtension = std::array<u8, 3>;
+using UniqueSerialNumber = std::array<u8, 10>;
// This is nn::nfc::DeviceHandle
using DeviceHandle = u64;
@@ -78,7 +80,6 @@ using DeviceHandle = u64;
// This is nn::nfc::TagInfo
struct TagInfo {
UniqueSerialNumber uuid;
- UniqueSerialNumberExtension uuid_extension;
u8 uuid_length;
INSERT_PADDING_BYTES(0x15);
NfcProtocol protocol;
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index 7d36d5ee6..aed12a7f8 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -85,7 +85,7 @@ enum class CabinetMode : u8 {
StartFormatter,
};
-using LockBytes = std::array<u8, 2>;
+using UuidPart = std::array<u8, 3>;
using HashData = std::array<u8, 0x20>;
using ApplicationArea = std::array<u8, 0xD8>;
using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>;
@@ -93,12 +93,20 @@ using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>;
// This is nn::nfp::TagInfo
using TagInfo = NFC::TagInfo;
+struct NtagTagUuid {
+ UuidPart part1;
+ UuidPart part2;
+ u8 nintendo_id;
+};
+static_assert(sizeof(NtagTagUuid) == 7, "NtagTagUuid is an invalid size");
+
struct TagUuid {
- NFC::UniqueSerialNumber uid;
+ UuidPart part1;
+ u8 crc_check1;
+ UuidPart part2;
u8 nintendo_id;
- LockBytes lock_bytes;
};
-static_assert(sizeof(TagUuid) == 10, "TagUuid is an invalid size");
+static_assert(sizeof(TagUuid) == 8, "TagUuid is an invalid size");
struct WriteDate {
u16 year;
@@ -231,7 +239,8 @@ struct EncryptedAmiiboFile {
static_assert(sizeof(EncryptedAmiiboFile) == 0x1F8, "AmiiboFile is an invalid size");
struct NTAG215File {
- LockBytes lock_bytes; // Tag UUID
+ u8 uid_crc_check2;
+ u8 internal_number;
u16 static_lock; // Set defined pages as read only
u32 compability_container; // Defines available memory
HashData hmac_data; // Hash
@@ -250,8 +259,7 @@ struct NTAG215File {
u32_be register_info_crc;
ApplicationArea application_area; // Encrypted Game data
HashData hmac_tag; // Hash
- NFC::UniqueSerialNumber uid; // Unique serial number
- u8 nintendo_id; // Tag UUID
+ TagUuid uid;
AmiiboModelInfo model_info;
HashData keygen_salt; // Salt
u32 dynamic_lock; // Dynamic lock
@@ -264,7 +272,9 @@ static_assert(std::is_trivially_copyable_v<NTAG215File>, "NTAG215File must be tr
#pragma pack()
struct EncryptedNTAG215File {
- TagUuid uuid; // Unique serial number
+ TagUuid uuid;
+ u8 uuid_crc_check2;
+ u8 internal_number;
u16 static_lock; // Set defined pages as read only
u32 compability_container; // Defines available memory
EncryptedAmiiboFile user_memory; // Writable data
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h
index ab1f30f9e..a04538d5d 100644
--- a/src/core/hle/service/nvdrv/devices/nvdevice.h
+++ b/src/core/hle/service/nvdrv/devices/nvdevice.h
@@ -34,7 +34,7 @@ public:
* @returns The result code of the ioctl.
*/
virtual NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) = 0;
+ std::span<u8> output) = 0;
/**
* Handles an ioctl2 request.
@@ -45,7 +45,7 @@ public:
* @returns The result code of the ioctl.
*/
virtual NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) = 0;
+ std::span<const u8> inline_input, std::span<u8> output) = 0;
/**
* Handles an ioctl3 request.
@@ -56,7 +56,7 @@ public:
* @returns The result code of the ioctl.
*/
virtual NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) = 0;
+ std::span<u8> output, std::span<u8> inline_output) = 0;
/**
* Called once a device is opened
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 5a5b2e305..05a43d8dc 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -18,19 +18,19 @@ nvdisp_disp0::nvdisp_disp0(Core::System& system_, NvCore::Container& core)
nvdisp_disp0::~nvdisp_disp0() = default;
NvResult nvdisp_disp0::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvdisp_disp0::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+ std::span<u8> output, std::span<u8> inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
@@ -51,8 +51,8 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat form
stride, format, transform, crop_rect};
system.GPU().RequestSwapBuffers(&framebuffer, fences, num_fences);
- system.GetPerfStats().EndSystemFrame();
system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs());
+ system.GetPerfStats().EndSystemFrame();
system.GetPerfStats().BeginSystemFrame();
}
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index bcd0e3ed5..daee05fe8 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -26,11 +26,11 @@ public:
~nvdisp_disp0() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 681bd0867..07e570a9f 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -28,7 +28,7 @@ nvhost_as_gpu::nvhost_as_gpu(Core::System& system_, Module& module_, NvCore::Con
nvhost_as_gpu::~nvhost_as_gpu() = default;
NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 'A':
switch (command.cmd) {
@@ -61,13 +61,13 @@ NvResult nvhost_as_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> i
}
NvResult nvhost_as_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+ std::span<u8> output, std::span<u8> inline_output) {
switch (command.group) {
case 'A':
switch (command.cmd) {
@@ -87,7 +87,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
void nvhost_as_gpu::OnOpen(DeviceFD fd) {}
void nvhost_as_gpu::OnClose(DeviceFD fd) {}
-NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::span<u8> output) {
IoctlAllocAsEx params{};
std::memcpy(&params, input.data(), input.size());
@@ -141,7 +141,7 @@ NvResult nvhost_as_gpu::AllocAsEx(std::span<const u8> input, std::vector<u8>& ou
return NvResult::Success;
}
-NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::AllocateSpace(std::span<const u8> input, std::span<u8> output) {
IoctlAllocSpace params{};
std::memcpy(&params, input.data(), input.size());
@@ -220,7 +220,7 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {
mapping_map.erase(offset);
}
-NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::span<u8> output) {
IoctlFreeSpace params{};
std::memcpy(&params, input.data(), input.size());
@@ -266,15 +266,14 @@ NvResult nvhost_as_gpu::FreeSpace(std::span<const u8> input, std::vector<u8>& ou
return NvResult::Success;
}
-NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::span<u8> output) {
const auto num_entries = input.size() / sizeof(IoctlRemapEntry);
LOG_DEBUG(Service_NVDRV, "called, num_entries=0x{:X}", num_entries);
- std::vector<IoctlRemapEntry> entries(num_entries);
- std::memcpy(entries.data(), input.data(), input.size());
-
std::scoped_lock lock(mutex);
+ entries.resize_destructive(num_entries);
+ std::memcpy(entries.data(), input.data(), input.size());
if (!vm.initialised) {
return NvResult::BadValue;
@@ -320,7 +319,7 @@ NvResult nvhost_as_gpu::Remap(std::span<const u8> input, std::vector<u8>& output
return NvResult::Success;
}
-NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::span<u8> output) {
IoctlMapBufferEx params{};
std::memcpy(&params, input.data(), input.size());
@@ -424,7 +423,7 @@ NvResult nvhost_as_gpu::MapBufferEx(std::span<const u8> input, std::vector<u8>&
return NvResult::Success;
}
-NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::span<u8> output) {
IoctlUnmapBuffer params{};
std::memcpy(&params, input.data(), input.size());
@@ -463,7 +462,7 @@ NvResult nvhost_as_gpu::UnmapBuffer(std::span<const u8> input, std::vector<u8>&
return NvResult::Success;
}
-NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::BindChannel(std::span<const u8> input, std::span<u8> output) {
IoctlBindChannel params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={:X}", params.fd);
@@ -492,7 +491,7 @@ void nvhost_as_gpu::GetVARegionsImpl(IoctlGetVaRegions& params) {
};
}
-NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output) {
IoctlGetVaRegions params{};
std::memcpy(&params, input.data(), input.size());
@@ -511,8 +510,8 @@ NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>&
return NvResult::Success;
}
-NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) {
+NvResult nvhost_as_gpu::GetVARegions(std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) {
IoctlGetVaRegions params{};
std::memcpy(&params, input.data(), input.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index 1aba8d579..2af3e1260 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -15,6 +15,7 @@
#include "common/address_space.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/scratch_buffer.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
@@ -48,11 +49,11 @@ public:
~nvhost_as_gpu() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
@@ -138,18 +139,18 @@ private:
static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(VaRegion) * 2,
"IoctlGetVaRegions is incorrect size");
- NvResult AllocAsEx(std::span<const u8> input, std::vector<u8>& output);
- NvResult AllocateSpace(std::span<const u8> input, std::vector<u8>& output);
- NvResult Remap(std::span<const u8> input, std::vector<u8>& output);
- NvResult MapBufferEx(std::span<const u8> input, std::vector<u8>& output);
- NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output);
- NvResult FreeSpace(std::span<const u8> input, std::vector<u8>& output);
- NvResult BindChannel(std::span<const u8> input, std::vector<u8>& output);
+ NvResult AllocAsEx(std::span<const u8> input, std::span<u8> output);
+ NvResult AllocateSpace(std::span<const u8> input, std::span<u8> output);
+ NvResult Remap(std::span<const u8> input, std::span<u8> output);
+ NvResult MapBufferEx(std::span<const u8> input, std::span<u8> output);
+ NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output);
+ NvResult FreeSpace(std::span<const u8> input, std::span<u8> output);
+ NvResult BindChannel(std::span<const u8> input, std::span<u8> output);
void GetVARegionsImpl(IoctlGetVaRegions& params);
- NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output);
- NvResult GetVARegions(std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output);
+ NvResult GetVARegions(std::span<const u8> input, std::span<u8> output);
+ NvResult GetVARegions(std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output);
void FreeMappingLocked(u64 offset);
@@ -212,6 +213,7 @@ private:
bool initialised{};
} vm;
std::shared_ptr<Tegra::MemoryManager> gmmu;
+ Common::ScratchBuffer<IoctlRemapEntry> entries;
// s32 channel{};
// u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index e12025560..4d55554b4 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -35,7 +35,7 @@ nvhost_ctrl::~nvhost_ctrl() {
}
NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 0x0:
switch (command.cmd) {
@@ -64,13 +64,13 @@ NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inp
}
NvResult nvhost_ctrl::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_outpu) {
+ std::span<u8> output, std::span<u8> inline_outpu) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
@@ -79,7 +79,7 @@ void nvhost_ctrl::OnOpen(DeviceFD fd) {}
void nvhost_ctrl::OnClose(DeviceFD fd) {}
-NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output) {
IocGetConfigParams params{};
std::memcpy(&params, input.data(), sizeof(params));
LOG_TRACE(Service_NVDRV, "called, setting={}!{}", params.domain_str.data(),
@@ -87,7 +87,7 @@ NvResult nvhost_ctrl::NvOsGetConfigU32(std::span<const u8> input, std::vector<u8
return NvResult::ConfigVarNotFound; // Returns error on production mode
}
-NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output,
+NvResult nvhost_ctrl::IocCtrlEventWait(std::span<const u8> input, std::span<u8> output,
bool is_allocation) {
IocCtrlEventWaitParams params{};
std::memcpy(&params, input.data(), sizeof(params));
@@ -231,7 +231,7 @@ NvResult nvhost_ctrl::FreeEvent(u32 slot) {
return NvResult::Success;
}
-NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output) {
IocCtrlEventRegisterParams params{};
std::memcpy(&params, input.data(), sizeof(params));
const u32 event_id = params.user_event_id;
@@ -252,7 +252,7 @@ NvResult nvhost_ctrl::IocCtrlEventRegister(std::span<const u8> input, std::vecto
return NvResult::Success;
}
-NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output) {
IocCtrlEventUnregisterParams params{};
std::memcpy(&params, input.data(), sizeof(params));
const u32 event_id = params.user_event_id & 0x00FF;
@@ -262,8 +262,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregister(std::span<const u8> input, std::vec
return FreeEvent(event_id);
}
-NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input,
- std::vector<u8>& output) {
+NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output) {
IocCtrlEventUnregisterBatchParams params{};
std::memcpy(&params, input.data(), sizeof(params));
u64 event_mask = params.user_events;
@@ -281,7 +280,7 @@ NvResult nvhost_ctrl::IocCtrlEventUnregisterBatch(std::span<const u8> input,
return NvResult::Success;
}
-NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl::IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output) {
IocCtrlEventClearParams params{};
std::memcpy(&params, input.data(), sizeof(params));
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index dd2e7888a..2efed4862 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -26,11 +26,11 @@ public:
~nvhost_ctrl() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
@@ -186,13 +186,12 @@ private:
static_assert(sizeof(IocCtrlEventUnregisterBatchParams) == 8,
"IocCtrlEventKill is incorrect size");
- NvResult NvOsGetConfigU32(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocCtrlEventWait(std::span<const u8> input, std::vector<u8>& output,
- bool is_allocation);
- NvResult IocCtrlEventRegister(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocCtrlEventUnregister(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocCtrlClearEventWait(std::span<const u8> input, std::vector<u8>& output);
+ NvResult NvOsGetConfigU32(std::span<const u8> input, std::span<u8> output);
+ NvResult IocCtrlEventWait(std::span<const u8> input, std::span<u8> output, bool is_allocation);
+ NvResult IocCtrlEventRegister(std::span<const u8> input, std::span<u8> output);
+ NvResult IocCtrlEventUnregister(std::span<const u8> input, std::span<u8> output);
+ NvResult IocCtrlEventUnregisterBatch(std::span<const u8> input, std::span<u8> output);
+ NvResult IocCtrlClearEventWait(std::span<const u8> input, std::span<u8> output);
NvResult FreeEvent(u32 slot);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index be3c083db..6081d92e9 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -22,7 +22,7 @@ nvhost_ctrl_gpu::~nvhost_ctrl_gpu() {
}
NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 'G':
switch (command.cmd) {
@@ -54,13 +54,13 @@ NvResult nvhost_ctrl_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8>
}
NvResult nvhost_ctrl_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+ std::span<u8> output, std::span<u8> inline_output) {
switch (command.group) {
case 'G':
switch (command.cmd) {
@@ -82,7 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {}
void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {}
-NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlCharacteristics params{};
std::memcpy(&params, input.data(), input.size());
@@ -127,8 +127,8 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vec
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) {
+NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlCharacteristics params{};
std::memcpy(&params, input.data(), input.size());
@@ -175,7 +175,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics(std::span<const u8> input, std::vec
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output) {
IoctlGpuGetTpcMasksArgs params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
@@ -186,8 +186,8 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) {
+NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) {
IoctlGpuGetTpcMasksArgs params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size=0x{:X}", params.mask_buffer_size);
@@ -199,7 +199,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks(std::span<const u8> input, std::vector<u8>
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::span<u8> output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlActiveSlotMask params{};
@@ -212,7 +212,7 @@ NvResult nvhost_ctrl_gpu::GetActiveSlotMask(std::span<const u8> input, std::vect
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlZcullGetCtxSize params{};
@@ -224,7 +224,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetCtxSize(std::span<const u8> input, std::vector
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::span<u8> output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlNvgpuGpuZcullGetInfoArgs params{};
@@ -247,7 +247,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(std::span<const u8> input, std::vector<u8
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::span<u8> output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcSetTable params{};
@@ -263,7 +263,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(std::span<const u8> input, std::vector<u8>
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::span<u8> output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcQueryTable params{};
@@ -273,7 +273,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(std::span<const u8> input, std::vector<u
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::span<u8> output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlFlushL2 params{};
@@ -283,7 +283,7 @@ NvResult nvhost_ctrl_gpu::FlushL2(std::span<const u8> input, std::vector<u8>& ou
return NvResult::Success;
}
-NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_ctrl_gpu::GetGpuTime(std::span<const u8> input, std::span<u8> output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlGetGpuTime params{};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
index b9333d9d3..97995551c 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -22,11 +22,11 @@ public:
~nvhost_ctrl_gpu() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
@@ -151,21 +151,21 @@ private:
};
static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size");
- NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output);
- NvResult GetCharacteristics(std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output);
-
- NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output);
- NvResult GetTPCMasks(std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output);
-
- NvResult GetActiveSlotMask(std::span<const u8> input, std::vector<u8>& output);
- NvResult ZCullGetCtxSize(std::span<const u8> input, std::vector<u8>& output);
- NvResult ZCullGetInfo(std::span<const u8> input, std::vector<u8>& output);
- NvResult ZBCSetTable(std::span<const u8> input, std::vector<u8>& output);
- NvResult ZBCQueryTable(std::span<const u8> input, std::vector<u8>& output);
- NvResult FlushL2(std::span<const u8> input, std::vector<u8>& output);
- NvResult GetGpuTime(std::span<const u8> input, std::vector<u8>& output);
+ NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output);
+ NvResult GetCharacteristics(std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output);
+
+ NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output);
+ NvResult GetTPCMasks(std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output);
+
+ NvResult GetActiveSlotMask(std::span<const u8> input, std::span<u8> output);
+ NvResult ZCullGetCtxSize(std::span<const u8> input, std::span<u8> output);
+ NvResult ZCullGetInfo(std::span<const u8> input, std::span<u8> output);
+ NvResult ZBCSetTable(std::span<const u8> input, std::span<u8> output);
+ NvResult ZBCQueryTable(std::span<const u8> input, std::span<u8> output);
+ NvResult FlushL2(std::span<const u8> input, std::span<u8> output);
+ NvResult GetGpuTime(std::span<const u8> input, std::span<u8> output);
EventInterface& events_interface;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 453a965dc..46a25fcab 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -47,7 +47,7 @@ nvhost_gpu::~nvhost_gpu() {
}
NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 0x0:
switch (command.cmd) {
@@ -99,7 +99,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
};
NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
switch (command.group) {
case 'H':
switch (command.cmd) {
@@ -113,7 +113,7 @@ NvResult nvhost_gpu::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> inpu
}
NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+ std::span<u8> output, std::span<u8> inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
@@ -121,7 +121,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
void nvhost_gpu::OnOpen(DeviceFD fd) {}
void nvhost_gpu::OnClose(DeviceFD fd) {}
-NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) {
IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
@@ -130,7 +130,7 @@ NvResult nvhost_gpu::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& outp
return NvResult::Success;
}
-NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::span<u8> output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{};
@@ -139,7 +139,7 @@ NvResult nvhost_gpu::SetClientData(std::span<const u8> input, std::vector<u8>& o
return NvResult::Success;
}
-NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::span<u8> output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlClientData params{};
@@ -149,7 +149,7 @@ NvResult nvhost_gpu::GetClientData(std::span<const u8> input, std::vector<u8>& o
return NvResult::Success;
}
-NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::span<u8> output) {
std::memcpy(&zcull_params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, gpu_va={:X}, mode={:X}", zcull_params.gpu_va,
zcull_params.mode);
@@ -158,7 +158,7 @@ NvResult nvhost_gpu::ZCullBind(std::span<const u8> input, std::vector<u8>& outpu
return NvResult::Success;
}
-NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::span<u8> output) {
IoctlSetErrorNotifier params{};
std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, offset={:X}, size={:X}, mem={:X}", params.offset,
@@ -168,14 +168,14 @@ NvResult nvhost_gpu::SetErrorNotifier(std::span<const u8> input, std::vector<u8>
return NvResult::Success;
}
-NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::SetChannelPriority(std::span<const u8> input, std::span<u8> output) {
std::memcpy(&channel_priority, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority);
return NvResult::Success;
}
-NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output) {
IoctlAllocGpfifoEx2 params{};
std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV,
@@ -197,7 +197,7 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>&
return NvResult::Success;
}
-NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::span<u8> output) {
IoctlAllocObjCtx params{};
std::memcpy(&params, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called, class_num={:X}, flags={:X}", params.class_num,
@@ -208,7 +208,8 @@ NvResult nvhost_gpu::AllocateObjectContext(std::span<const u8> input, std::vecto
return NvResult::Success;
}
-static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) {
+static boost::container::small_vector<Tegra::CommandHeader, 512> BuildWaitCommandList(
+ NvFence fence) {
return {
Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1,
Tegra::SubmissionMode::Increasing),
@@ -219,35 +220,35 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(NvFence fence) {
};
}
-static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(NvFence fence) {
- std::vector<Tegra::CommandHeader> result{
+static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementCommandList(
+ NvFence fence) {
+ boost::container::small_vector<Tegra::CommandHeader, 512> result{
Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointPayload, 1,
Tegra::SubmissionMode::Increasing),
{}};
for (u32 count = 0; count < 2; ++count) {
- result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1,
- Tegra::SubmissionMode::Increasing));
- result.emplace_back(
+ result.push_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::SyncpointOperation, 1,
+ Tegra::SubmissionMode::Increasing));
+ result.push_back(
BuildFenceAction(Tegra::Engines::Puller::FenceOperation::Increment, fence.id));
}
return result;
}
-static std::vector<Tegra::CommandHeader> BuildIncrementWithWfiCommandList(NvFence fence) {
- std::vector<Tegra::CommandHeader> result{
+static boost::container::small_vector<Tegra::CommandHeader, 512> BuildIncrementWithWfiCommandList(
+ NvFence fence) {
+ boost::container::small_vector<Tegra::CommandHeader, 512> result{
Tegra::BuildCommandHeader(Tegra::BufferMethods::WaitForIdle, 1,
Tegra::SubmissionMode::Increasing),
{}};
- const std::vector<Tegra::CommandHeader> increment{BuildIncrementCommandList(fence)};
-
- result.insert(result.end(), increment.begin(), increment.end());
-
+ auto increment_list{BuildIncrementCommandList(fence)};
+ result.insert(result.end(), increment_list.begin(), increment_list.end());
return result;
}
-NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output,
+NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output,
Tegra::CommandList&& entries) {
LOG_TRACE(Service_NVDRV, "called, gpfifo={:X}, num_entries={:X}, flags={:X}", params.address,
params.num_entries, params.flags.raw);
@@ -293,7 +294,7 @@ NvResult nvhost_gpu::SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>
return NvResult::Success;
}
-NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output,
+NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output,
bool kickoff) {
if (input.size() < sizeof(IoctlSubmitGpfifo)) {
UNIMPLEMENTED();
@@ -315,7 +316,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>
}
NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
- std::vector<u8>& output) {
+ std::span<u8> output) {
if (input.size() < sizeof(IoctlSubmitGpfifo)) {
UNIMPLEMENTED();
return NvResult::InvalidSize;
@@ -327,7 +328,7 @@ NvResult nvhost_gpu::SubmitGPFIFOBase(std::span<const u8> input, std::span<const
return SubmitGPFIFOImpl(params, output, std::move(entries));
}
-NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::span<u8> output) {
IoctlGetWaitbase params{};
std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
LOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
@@ -337,7 +338,7 @@ NvResult nvhost_gpu::GetWaitbase(std::span<const u8> input, std::vector<u8>& out
return NvResult::Success;
}
-NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::span<u8> output) {
IoctlChannelSetTimeout params{};
std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
@@ -345,7 +346,7 @@ NvResult nvhost_gpu::ChannelSetTimeout(std::span<const u8> input, std::vector<u8
return NvResult::Success;
}
-NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_gpu::ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output) {
IoctlSetTimeslice params{};
std::memcpy(&params, input.data(), sizeof(IoctlSetTimeslice));
LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 3ca58202d..529c20526 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -41,11 +41,11 @@ public:
~nvhost_gpu() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
@@ -186,23 +186,23 @@ private:
u32_le channel_priority{};
u32_le channel_timeslice{};
- NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output);
- NvResult SetClientData(std::span<const u8> input, std::vector<u8>& output);
- NvResult GetClientData(std::span<const u8> input, std::vector<u8>& output);
- NvResult ZCullBind(std::span<const u8> input, std::vector<u8>& output);
- NvResult SetErrorNotifier(std::span<const u8> input, std::vector<u8>& output);
- NvResult SetChannelPriority(std::span<const u8> input, std::vector<u8>& output);
- NvResult AllocGPFIFOEx2(std::span<const u8> input, std::vector<u8>& output);
- NvResult AllocateObjectContext(std::span<const u8> input, std::vector<u8>& output);
- NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::vector<u8>& output,
+ NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output);
+ NvResult SetClientData(std::span<const u8> input, std::span<u8> output);
+ NvResult GetClientData(std::span<const u8> input, std::span<u8> output);
+ NvResult ZCullBind(std::span<const u8> input, std::span<u8> output);
+ NvResult SetErrorNotifier(std::span<const u8> input, std::span<u8> output);
+ NvResult SetChannelPriority(std::span<const u8> input, std::span<u8> output);
+ NvResult AllocGPFIFOEx2(std::span<const u8> input, std::span<u8> output);
+ NvResult AllocateObjectContext(std::span<const u8> input, std::span<u8> output);
+ NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, std::span<u8> output,
Tegra::CommandList&& entries);
- NvResult SubmitGPFIFOBase(std::span<const u8> input, std::vector<u8>& output,
+ NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<u8> output,
bool kickoff = false);
NvResult SubmitGPFIFOBase(std::span<const u8> input, std::span<const u8> input_inline,
- std::vector<u8>& output);
- NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output);
- NvResult ChannelSetTimeout(std::span<const u8> input, std::vector<u8>& output);
- NvResult ChannelSetTimeslice(std::span<const u8> input, std::vector<u8>& output);
+ std::span<u8> output);
+ NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output);
+ NvResult ChannelSetTimeout(std::span<const u8> input, std::span<u8> output);
+ NvResult ChannelSetTimeslice(std::span<const u8> input, std::span<u8> output);
EventInterface& events_interface;
NvCore::Container& core;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index dc45169ad..a174442a6 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -16,7 +16,7 @@ nvhost_nvdec::nvhost_nvdec(Core::System& system_, NvCore::Container& core_)
nvhost_nvdec::~nvhost_nvdec() = default;
NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 0x0:
switch (command.cmd) {
@@ -56,13 +56,13 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
}
NvResult nvhost_nvdec::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+ std::span<u8> output, std::span<u8> inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index 0d615bbcb..ad2233c49 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -14,11 +14,11 @@ public:
~nvhost_nvdec() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 1ab51f10b..61649aa4a 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -36,7 +36,7 @@ std::size_t SliceVectors(std::span<const u8> input, std::vector<T>& dst, std::si
// Writes the data in src to an offset into the dst vector. The offset is specified in bytes
// Returns the number of bytes written into dst.
template <typename T>
-std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::size_t offset) {
+std::size_t WriteVectors(std::span<u8> dst, const std::vector<T>& src, std::size_t offset) {
if (src.empty()) {
return 0;
}
@@ -72,8 +72,7 @@ NvResult nvhost_nvdec_common::SetNVMAPfd(std::span<const u8> input) {
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input,
- std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output) {
IoctlSubmit params{};
std::memcpy(&params, input.data(), sizeof(IoctlSubmit));
LOG_DEBUG(Service_NVDRV, "called NVDEC Submit, cmd_buffer_count={}", params.cmd_buffer_count);
@@ -121,7 +120,7 @@ NvResult nvhost_nvdec_common::Submit(DeviceFD fd, std::span<const u8> input,
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::span<u8> output) {
IoctlGetSyncpoint params{};
std::memcpy(&params, input.data(), sizeof(IoctlGetSyncpoint));
LOG_DEBUG(Service_NVDRV, "called GetSyncpoint, id={}", params.param);
@@ -133,7 +132,7 @@ NvResult nvhost_nvdec_common::GetSyncpoint(std::span<const u8> input, std::vecto
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::span<u8> output) {
IoctlGetWaitbase params{};
LOG_CRITICAL(Service_NVDRV, "called WAITBASE");
std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
@@ -142,7 +141,7 @@ NvResult nvhost_nvdec_common::GetWaitbase(std::span<const u8> input, std::vector
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::span<u8> output) {
IoctlMapBuffer params{};
std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
@@ -159,7 +158,7 @@ NvResult nvhost_nvdec_common::MapBuffer(std::span<const u8> input, std::vector<u
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::span<u8> output) {
IoctlMapBuffer params{};
std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
@@ -173,7 +172,7 @@ NvResult nvhost_nvdec_common::UnmapBuffer(std::span<const u8> input, std::vector
return NvResult::Success;
}
-NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_nvdec_common::SetSubmitTimeout(std::span<const u8> input, std::span<u8> output) {
std::memcpy(&submit_timeout, input.data(), input.size());
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
return NvResult::Success;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
index 5af26a26f..9bb573bfe 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
@@ -108,12 +108,12 @@ protected:
/// Ioctl command implementations
NvResult SetNVMAPfd(std::span<const u8> input);
- NvResult Submit(DeviceFD fd, std::span<const u8> input, std::vector<u8>& output);
- NvResult GetSyncpoint(std::span<const u8> input, std::vector<u8>& output);
- NvResult GetWaitbase(std::span<const u8> input, std::vector<u8>& output);
- NvResult MapBuffer(std::span<const u8> input, std::vector<u8>& output);
- NvResult UnmapBuffer(std::span<const u8> input, std::vector<u8>& output);
- NvResult SetSubmitTimeout(std::span<const u8> input, std::vector<u8>& output);
+ NvResult Submit(DeviceFD fd, std::span<const u8> input, std::span<u8> output);
+ NvResult GetSyncpoint(std::span<const u8> input, std::span<u8> output);
+ NvResult GetWaitbase(std::span<const u8> input, std::span<u8> output);
+ NvResult MapBuffer(std::span<const u8> input, std::span<u8> output);
+ NvResult UnmapBuffer(std::span<const u8> input, std::span<u8> output);
+ NvResult SetSubmitTimeout(std::span<const u8> input, std::span<u8> output);
Kernel::KEvent* QueryEvent(u32 event_id) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
index 39f30e7c8..a05c8cdae 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -13,7 +13,7 @@ nvhost_nvjpg::nvhost_nvjpg(Core::System& system_) : nvdevice{system_} {}
nvhost_nvjpg::~nvhost_nvjpg() = default;
NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 'H':
switch (command.cmd) {
@@ -32,13 +32,13 @@ NvResult nvhost_nvjpg::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
}
NvResult nvhost_nvjpg::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+ std::span<u8> output, std::span<u8> inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
@@ -46,7 +46,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
void nvhost_nvjpg::OnOpen(DeviceFD fd) {}
void nvhost_nvjpg::OnClose(DeviceFD fd) {}
-NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvhost_nvjpg::SetNVMAPfd(std::span<const u8> input, std::span<u8> output) {
IoctlSetNvmapFD params{};
std::memcpy(&params, input.data(), input.size());
LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
index 41b57e872..5623e0d47 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -16,11 +16,11 @@ public:
~nvhost_nvjpg() override;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
@@ -33,7 +33,7 @@ private:
s32_le nvmap_fd{};
- NvResult SetNVMAPfd(std::span<const u8> input, std::vector<u8>& output);
+ NvResult SetNVMAPfd(std::span<const u8> input, std::span<u8> output);
};
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index b0ea402a7..c0b8684c3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -16,7 +16,7 @@ nvhost_vic::nvhost_vic(Core::System& system_, NvCore::Container& core_)
nvhost_vic::~nvhost_vic() = default;
NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 0x0:
switch (command.cmd) {
@@ -56,13 +56,13 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
}
NvResult nvhost_vic::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+ std::span<u8> output, std::span<u8> inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
index b5e350a83..cadbcb0a5 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -13,11 +13,11 @@ public:
~nvhost_vic();
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 07417f045..e7f7e273b 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -26,7 +26,7 @@ nvmap::nvmap(Core::System& system_, NvCore::Container& container_)
nvmap::~nvmap() = default;
NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
switch (command.group) {
case 0x1:
switch (command.cmd) {
@@ -55,13 +55,13 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
}
NvResult nvmap::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
-NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) {
UNIMPLEMENTED_MSG("Unimplemented ioctl={:08X}", command.raw);
return NvResult::NotImplemented;
}
@@ -69,7 +69,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
void nvmap::OnOpen(DeviceFD fd) {}
void nvmap::OnClose(DeviceFD fd) {}
-NvResult nvmap::IocCreate(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvmap::IocCreate(std::span<const u8> input, std::span<u8> output) {
IocCreateParams params;
std::memcpy(&params, input.data(), sizeof(params));
LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size);
@@ -89,7 +89,7 @@ NvResult nvmap::IocCreate(std::span<const u8> input, std::vector<u8>& output) {
return NvResult::Success;
}
-NvResult nvmap::IocAlloc(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {
IocAllocParams params;
std::memcpy(&params, input.data(), sizeof(params));
LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address);
@@ -137,7 +137,7 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::vector<u8>& output) {
return result;
}
-NvResult nvmap::IocGetId(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvmap::IocGetId(std::span<const u8> input, std::span<u8> output) {
IocGetIdParams params;
std::memcpy(&params, input.data(), sizeof(params));
@@ -161,7 +161,7 @@ NvResult nvmap::IocGetId(std::span<const u8> input, std::vector<u8>& output) {
return NvResult::Success;
}
-NvResult nvmap::IocFromId(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvmap::IocFromId(std::span<const u8> input, std::span<u8> output) {
IocFromIdParams params;
std::memcpy(&params, input.data(), sizeof(params));
@@ -192,7 +192,7 @@ NvResult nvmap::IocFromId(std::span<const u8> input, std::vector<u8>& output) {
return NvResult::Success;
}
-NvResult nvmap::IocParam(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvmap::IocParam(std::span<const u8> input, std::span<u8> output) {
enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 };
IocParamParams params;
@@ -241,7 +241,7 @@ NvResult nvmap::IocParam(std::span<const u8> input, std::vector<u8>& output) {
return NvResult::Success;
}
-NvResult nvmap::IocFree(std::span<const u8> input, std::vector<u8>& output) {
+NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {
IocFreeParams params;
std::memcpy(&params, input.data(), sizeof(params));
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 82bd3b118..40c65b430 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -27,11 +27,11 @@ public:
nvmap& operator=(const nvmap&) = delete;
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) override;
+ std::span<u8> output) override;
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) override;
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output) override;
+ std::span<const u8> inline_input, std::span<u8> output) override;
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) override;
void OnOpen(DeviceFD fd) override;
void OnClose(DeviceFD fd) override;
@@ -106,12 +106,12 @@ private:
};
static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size");
- NvResult IocCreate(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocAlloc(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocGetId(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocFromId(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocParam(std::span<const u8> input, std::vector<u8>& output);
- NvResult IocFree(std::span<const u8> input, std::vector<u8>& output);
+ NvResult IocCreate(std::span<const u8> input, std::span<u8> output);
+ NvResult IocAlloc(std::span<const u8> input, std::span<u8> output);
+ NvResult IocGetId(std::span<const u8> input, std::span<u8> output);
+ NvResult IocFromId(std::span<const u8> input, std::span<u8> output);
+ NvResult IocParam(std::span<const u8> input, std::span<u8> output);
+ NvResult IocFree(std::span<const u8> input, std::span<u8> output);
NvCore::Container& container;
NvCore::NvMap& file;
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 3d774eec4..9e46ee8dd 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -130,7 +130,7 @@ DeviceFD Module::Open(const std::string& device_name) {
}
NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output) {
+ std::span<u8> output) {
if (fd < 0) {
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
return NvResult::InvalidState;
@@ -147,7 +147,7 @@ NvResult Module::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
}
NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output) {
+ std::span<const u8> inline_input, std::span<u8> output) {
if (fd < 0) {
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
return NvResult::InvalidState;
@@ -163,8 +163,8 @@ NvResult Module::Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
return itr->second->Ioctl2(fd, command, input, inline_input, output);
}
-NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::vector<u8>& output, std::vector<u8>& inline_output) {
+NvResult Module::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output) {
if (fd < 0) {
LOG_ERROR(Service_NVDRV, "Invalid DeviceFD={}!", fd);
return NvResult::InvalidState;
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 668be742b..d8622b3ca 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -80,13 +80,13 @@ public:
DeviceFD Open(const std::string& device_name);
/// Sends an ioctl command to the specified file descriptor.
- NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output);
+ NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output);
NvResult Ioctl2(DeviceFD fd, Ioctl command, std::span<const u8> input,
- std::span<const u8> inline_input, std::vector<u8>& output);
+ std::span<const u8> inline_input, std::span<u8> output);
- NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::vector<u8>& output,
- std::vector<u8>& inline_output);
+ NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
+ std::span<u8> inline_output);
/// Closes a device file descriptor and returns operation success.
NvResult Close(DeviceFD fd);
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
index d010a1e03..348207e25 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
@@ -63,12 +63,12 @@ void NVDRV::Ioctl1(HLERequestContext& ctx) {
}
// Check device
- std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
+ tmp_output.resize_destructive(ctx.GetWriteBufferSize(0));
const auto input_buffer = ctx.ReadBuffer(0);
- const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, output_buffer);
+ const auto nv_result = nvdrv->Ioctl1(fd, command, input_buffer, tmp_output);
if (command.is_out != 0) {
- ctx.WriteBuffer(output_buffer);
+ ctx.WriteBuffer(tmp_output);
}
IPC::ResponseBuilder rb{ctx, 3};
@@ -90,12 +90,12 @@ void NVDRV::Ioctl2(HLERequestContext& ctx) {
const auto input_buffer = ctx.ReadBuffer(0);
const auto input_inlined_buffer = ctx.ReadBuffer(1);
- std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
+ tmp_output.resize_destructive(ctx.GetWriteBufferSize(0));
const auto nv_result =
- nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, output_buffer);
+ nvdrv->Ioctl2(fd, command, input_buffer, input_inlined_buffer, tmp_output);
if (command.is_out != 0) {
- ctx.WriteBuffer(output_buffer);
+ ctx.WriteBuffer(tmp_output);
}
IPC::ResponseBuilder rb{ctx, 3};
@@ -116,14 +116,12 @@ void NVDRV::Ioctl3(HLERequestContext& ctx) {
}
const auto input_buffer = ctx.ReadBuffer(0);
- std::vector<u8> output_buffer(ctx.GetWriteBufferSize(0));
- std::vector<u8> output_buffer_inline(ctx.GetWriteBufferSize(1));
-
- const auto nv_result =
- nvdrv->Ioctl3(fd, command, input_buffer, output_buffer, output_buffer_inline);
+ tmp_output.resize_destructive(ctx.GetWriteBufferSize(0));
+ tmp_output_inline.resize_destructive(ctx.GetWriteBufferSize(1));
+ const auto nv_result = nvdrv->Ioctl3(fd, command, input_buffer, tmp_output, tmp_output_inline);
if (command.is_out != 0) {
- ctx.WriteBuffer(output_buffer, 0);
- ctx.WriteBuffer(output_buffer_inline, 1);
+ ctx.WriteBuffer(tmp_output, 0);
+ ctx.WriteBuffer(tmp_output_inline, 1);
}
IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h
index 881ea1a6b..4b593ff90 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.h
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.h
@@ -4,6 +4,7 @@
#pragma once
#include <memory>
+#include "common/scratch_buffer.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/service.h"
@@ -33,6 +34,8 @@ private:
u64 pid{};
bool is_initialized{};
+ Common::ScratchBuffer<u8> tmp_output;
+ Common::ScratchBuffer<u8> tmp_output_inline;
};
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index da2d5890f..5f55cd31e 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -43,14 +43,10 @@ void Nvnflinger::SplitVSync(std::stop_token stop_token) {
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
while (!stop_token.stop_requested()) {
- vsync_signal.wait(false);
- vsync_signal.store(false);
-
- guard->lock();
+ vsync_signal.Wait();
+ const auto lock_guard = Lock();
Compose();
-
- guard->unlock();
}
}
@@ -69,8 +65,8 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
"ScreenComposition",
[this](std::uintptr_t, s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
- vsync_signal.store(true);
- vsync_signal.notify_all();
+ { const auto lock_guard = Lock(); }
+ vsync_signal.Set();
return std::chrono::nanoseconds(GetNextTicks());
});
@@ -96,8 +92,7 @@ Nvnflinger::~Nvnflinger() {
if (system.IsMulticore()) {
system.CoreTiming().UnscheduleEvent(multi_composition_event, {});
vsync_thread.request_stop();
- vsync_signal.store(true);
- vsync_signal.notify_all();
+ vsync_signal.Set();
} else {
system.CoreTiming().UnscheduleEvent(single_composition_event, {});
}
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index a043cceb2..ef236303a 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -12,6 +12,7 @@
#include "common/common_types.h"
#include "common/polyfill_thread.h"
+#include "common/thread.h"
#include "core/hle/result.h"
#include "core/hle/service/kernel_helpers.h"
@@ -143,7 +144,7 @@ private:
Core::System& system;
- std::atomic<bool> vsync_signal;
+ Common::Event vsync_signal;
std::jthread vsync_thread;
diff --git a/src/core/hle/service/nvnflinger/parcel.h b/src/core/hle/service/nvnflinger/parcel.h
index fb56d75d7..23ba315a0 100644
--- a/src/core/hle/service/nvnflinger/parcel.h
+++ b/src/core/hle/service/nvnflinger/parcel.h
@@ -6,6 +6,7 @@
#include <memory>
#include <span>
#include <vector>
+#include <boost/container/small_vector.hpp>
#include "common/alignment.h"
#include "common/assert.h"
@@ -167,7 +168,7 @@ public:
private:
template <typename T>
requires(std::is_trivially_copyable_v<T>)
- void WriteImpl(const T& val, std::vector<u8>& buffer) {
+ void WriteImpl(const T& val, boost::container::small_vector<u8, 0x200>& buffer) {
const size_t aligned_size = Common::AlignUp(sizeof(T), 4);
const size_t old_size = buffer.size();
buffer.resize(old_size + aligned_size);
@@ -176,8 +177,8 @@ private:
}
private:
- std::vector<u8> m_data_buffer;
- std::vector<u8> m_object_buffer;
+ boost::container::small_vector<u8, 0x200> m_data_buffer;
+ boost::container::small_vector<u8, 0x200> m_object_buffer;
};
} // namespace Service::android
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp
index 156bc27d8..d1e99b184 100644
--- a/src/core/hle/service/server_manager.cpp
+++ b/src/core/hle/service/server_manager.cpp
@@ -44,7 +44,7 @@ ServerManager::~ServerManager() {
m_event->Signal();
// Wait for processing to stop.
- m_stopped.wait(false);
+ m_stopped.Wait();
m_threads.clear();
// Clean up ports.
@@ -182,10 +182,7 @@ void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_thre
}
Result ServerManager::LoopProcess() {
- SCOPE_EXIT({
- m_stopped.store(true);
- m_stopped.notify_all();
- });
+ SCOPE_EXIT({ m_stopped.Set(); });
R_RETURN(this->LoopProcessImpl());
}
diff --git a/src/core/hle/service/server_manager.h b/src/core/hle/service/server_manager.h
index fdb8af2ff..58b0a0832 100644
--- a/src/core/hle/service/server_manager.h
+++ b/src/core/hle/service/server_manager.h
@@ -3,7 +3,6 @@
#pragma once
-#include <atomic>
#include <functional>
#include <list>
#include <map>
@@ -12,6 +11,7 @@
#include <vector>
#include "common/polyfill_thread.h"
+#include "common/thread.h"
#include "core/hle/result.h"
#include "core/hle/service/mutex.h"
@@ -82,7 +82,7 @@ private:
std::list<RequestState> m_deferrals{};
// Host state tracking
- std::atomic<bool> m_stopped{};
+ Common::Event m_stopped{};
std::vector<std::jthread> m_threads{};
std::stop_source m_stop_source{};
};
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
index e6293ffb9..9fc01ea90 100644
--- a/src/core/hle/service/time/clock_types.h
+++ b/src/core/hle/service/time/clock_types.h
@@ -3,6 +3,8 @@
#pragma once
+#include <ratio>
+
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/uuid.h"
@@ -74,18 +76,19 @@ static_assert(std::is_trivially_copyable_v<ContinuousAdjustmentTimePoint>,
/// https://switchbrew.org/wiki/Glue_services#TimeSpanType
struct TimeSpanType {
s64 nanoseconds{};
- static constexpr s64 ns_per_second{1000000000ULL};
s64 ToSeconds() const {
- return nanoseconds / ns_per_second;
+ return nanoseconds / std::nano::den;
}
static TimeSpanType FromSeconds(s64 seconds) {
- return {seconds * ns_per_second};
+ return {seconds * std::nano::den};
}
- static TimeSpanType FromTicks(u64 ticks, u64 frequency) {
- return FromSeconds(static_cast<s64>(ticks) / static_cast<s64>(frequency));
+ template <u64 Frequency>
+ static TimeSpanType FromTicks(u64 ticks) {
+ using TicksToNSRatio = std::ratio<std::nano::den, Frequency>;
+ return {static_cast<s64>(ticks * TicksToNSRatio::num / TicksToNSRatio::den)};
}
};
static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size");
diff --git a/src/core/hle/service/time/standard_steady_clock_core.cpp b/src/core/hle/service/time/standard_steady_clock_core.cpp
index 3dbbb9850..5627b7003 100644
--- a/src/core/hle/service/time/standard_steady_clock_core.cpp
+++ b/src/core/hle/service/time/standard_steady_clock_core.cpp
@@ -10,7 +10,7 @@ namespace Service::Time::Clock {
TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
const TimeSpanType ticks_time_span{
- TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
+ TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};
TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds};
if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) {
diff --git a/src/core/hle/service/time/tick_based_steady_clock_core.cpp b/src/core/hle/service/time/tick_based_steady_clock_core.cpp
index 27600413e..0d9fb3143 100644
--- a/src/core/hle/service/time/tick_based_steady_clock_core.cpp
+++ b/src/core/hle/service/time/tick_based_steady_clock_core.cpp
@@ -10,7 +10,7 @@ namespace Service::Time::Clock {
SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) {
const TimeSpanType ticks_time_span{
- TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
+ TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};
return {ticks_time_span.ToSeconds(), GetClockSourceId()};
}
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 868be60c5..7197ca30f 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -240,8 +240,8 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(HLERequestCon
const auto current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) {
- const auto ticks{Clock::TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(),
- Core::Hardware::CNTFREQ)};
+ const auto ticks{Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(
+ system.CoreTiming().GetClockTicks())};
const s64 base_time_point{context.offset + current_time_point.time_point -
ticks.ToSeconds()};
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index 28667710e..fa0fd0531 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -22,10 +22,6 @@ s64 GetSecondsSinceEpoch() {
return std::chrono::duration_cast<std::chrono::seconds>(time_since_epoch).count() +
Settings::values.custom_rtc_differential;
}
-
-s64 GetExternalRtcValue() {
- return GetSecondsSinceEpoch() + TimeManager::GetExternalTimeZoneOffset();
-}
} // Anonymous namespace
struct TimeManager::Impl final {
@@ -43,7 +39,7 @@ struct TimeManager::Impl final {
std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
time_zone_content_manager{system} {
- const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
+ const auto system_time{Clock::TimeSpanType::FromSeconds(GetSecondsSinceEpoch())};
SetupStandardSteadyClock(system, Common::UUID::MakeRandom(), system_time, {}, {});
SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
@@ -107,7 +103,7 @@ struct TimeManager::Impl final {
void SetupTimeZoneManager(std::string location_name,
Clock::SteadyClockTimePoint time_zone_updated_time_point,
- std::size_t total_location_name_count, u128 time_zone_rule_version,
+ std::vector<std::string> location_names, u128 time_zone_rule_version,
FileSys::VirtualFile& vfs_file) {
if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
location_name, vfs_file) != ResultSuccess) {
@@ -117,20 +113,13 @@ struct TimeManager::Impl final {
time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
- total_location_name_count);
+ location_names.size());
+ time_zone_content_manager.GetTimeZoneManager().SetLocationNames(location_names);
time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(
time_zone_rule_version);
time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
}
- static s64 GetExternalTimeZoneOffset() {
- // With "auto" timezone setting, we use the external system's timezone offset
- if (Settings::GetTimeZoneString() == "auto") {
- return Common::TimeZone::GetCurrentOffsetSeconds().count();
- }
- return 0;
- }
-
void SetupStandardSteadyClock(Core::System& system_, Common::UUID clock_source_id,
Clock::TimeSpanType setup_value,
Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) {
@@ -295,19 +284,10 @@ void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) {
void TimeManager::SetupTimeZoneManager(std::string location_name,
Clock::SteadyClockTimePoint time_zone_updated_time_point,
- std::size_t total_location_name_count,
+ std::vector<std::string> location_names,
u128 time_zone_rule_version,
FileSys::VirtualFile& vfs_file) {
- impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point,
- total_location_name_count, time_zone_rule_version, vfs_file);
+ impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, location_names,
+ time_zone_rule_version, vfs_file);
}
-
-/*static*/ s64 TimeManager::GetExternalTimeZoneOffset() {
- // With "auto" timezone setting, we use the external system's timezone offset
- if (Settings::GetTimeZoneString() == "auto") {
- return Common::TimeZone::GetCurrentOffsetSeconds().count();
- }
- return 0;
-}
-
} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h
index 4f046f266..84572dbfa 100644
--- a/src/core/hle/service/time/time_manager.h
+++ b/src/core/hle/service/time/time_manager.h
@@ -61,11 +61,9 @@ public:
void SetupTimeZoneManager(std::string location_name,
Clock::SteadyClockTimePoint time_zone_updated_time_point,
- std::size_t total_location_name_count, u128 time_zone_rule_version,
+ std::vector<std::string> location_names, u128 time_zone_rule_version,
FileSys::VirtualFile& vfs_file);
- static s64 GetExternalTimeZoneOffset();
-
private:
Core::System& system;
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp
index ce1c85bcc..a00676669 100644
--- a/src/core/hle/service/time/time_sharedmemory.cpp
+++ b/src/core/hle/service/time/time_sharedmemory.cpp
@@ -21,8 +21,9 @@ SharedMemory::~SharedMemory() = default;
void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id,
Clock::TimeSpanType current_time_point) {
- const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks(
- system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
+ const Clock::TimeSpanType ticks_time_span{
+ Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(
+ system.CoreTiming().GetClockTicks())};
const Clock::SteadyClockContext context{
static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),
clock_source_id};
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index afbfe9715..5d60be67a 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include <chrono>
#include <sstream>
#include "common/logging/log.h"
@@ -12,7 +13,11 @@
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.h"
#include "core/file_sys/system_archive/system_archive.h"
+#include "core/file_sys/vfs.h"
+#include "core/file_sys/vfs_types.h"
+#include "core/hle/result.h"
#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/time/errors.h"
#include "core/hle/service/time/time_manager.h"
#include "core/hle/service/time/time_zone_content_manager.h"
@@ -71,19 +76,13 @@ TimeZoneContentManager::TimeZoneContentManager(Core::System& system_)
: system{system_}, location_name_cache{BuildLocationNameCache(system)} {}
void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
- std::string location_name;
const auto timezone_setting = Settings::GetTimeZoneString();
- if (timezone_setting == "auto" || timezone_setting == "default") {
- location_name = Common::TimeZone::GetDefaultTimeZone();
- } else {
- location_name = timezone_setting;
- }
if (FileSys::VirtualFile vfs_file;
- GetTimeZoneInfoFile(location_name, vfs_file) == ResultSuccess) {
+ GetTimeZoneInfoFile(timezone_setting, vfs_file) == ResultSuccess) {
const auto time_point{
time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
- time_manager.SetupTimeZoneManager(location_name, time_point, location_name_cache.size(), {},
+ time_manager.SetupTimeZoneManager(timezone_setting, time_point, location_name_cache, {},
vfs_file);
} else {
time_zone_manager.MarkAsInitialized();
@@ -126,8 +125,15 @@ Result TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_n
vfs_file = zoneinfo_dir->GetFileRelative(location_name);
if (!vfs_file) {
- LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
- time_zone_binary_titleid, location_name);
+ LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using system timezone.",
+ time_zone_binary_titleid, location_name);
+ const std::string system_time_zone{Common::TimeZone::FindSystemTimeZone()};
+ vfs_file = zoneinfo_dir->GetFile(system_time_zone);
+ }
+
+ if (!vfs_file) {
+ LOG_WARNING(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
+ time_zone_binary_titleid, location_name);
vfs_file = zoneinfo_dir->GetFile(Common::TimeZone::GetDefaultTimeZone());
}
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp
index 973f7837a..205371a26 100644
--- a/src/core/hle/service/time/time_zone_manager.cpp
+++ b/src/core/hle/service/time/time_zone_manager.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <climits>
+#include <limits>
#include "common/assert.h"
#include "common/logging/log.h"
@@ -9,6 +10,7 @@
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/service/time/time_zone_manager.h"
+#include "core/hle/service/time/time_zone_types.h"
namespace Service::Time::TimeZone {
@@ -128,10 +130,10 @@ static constexpr int GetQZName(const char* name, int offset, char delimiter) {
}
static constexpr int GetTZName(const char* name, int offset) {
- for (char value{name[offset]};
- value != '\0' && !IsDigit(value) && value != ',' && value != '-' && value != '+';
- offset++) {
- value = name[offset];
+ char c;
+
+ while ((c = name[offset]) != '\0' && !IsDigit(c) && c != ',' && c != '-' && c != '+') {
+ ++offset;
}
return offset;
}
@@ -147,6 +149,7 @@ static constexpr bool GetInteger(const char* name, int& offset, int& value, int
if (value > max) {
return {};
}
+ offset++;
temp = name[offset];
} while (IsDigit(temp));
@@ -471,6 +474,13 @@ static bool ParsePosixName(const char* name, TimeZoneRule& rule) {
their_std_offset = their_offset;
}
}
+
+ if (rule.time_count > 0) {
+ UNIMPLEMENTED();
+ // TODO (lat9nq): Implement eggert/tz/localtime.c:tzparse:1329
+ // Seems to be unused in yuzu for now: I never hit the UNIMPLEMENTED in testing
+ }
+
rule.ttis[0].gmt_offset = -std_offset;
rule.ttis[0].is_dst = false;
rule.ttis[0].abbreviation_list_index = 0;
@@ -514,6 +524,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
constexpr s32 time_zone_max_leaps{50};
constexpr s32 time_zone_max_chars{50};
+ constexpr s32 time_zone_max_times{1000};
if (!(0 <= header.leap_count && header.leap_count < time_zone_max_leaps &&
0 < header.type_count && header.type_count < s32(time_zone_rule.ttis.size()) &&
0 <= header.time_count && header.time_count < s32(time_zone_rule.ats.size()) &&
@@ -546,7 +557,7 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
for (int index{}; index < time_zone_rule.time_count; ++index) {
const u8 type{*vfs_file->ReadByte(read_offset)};
read_offset += sizeof(u8);
- if (time_zone_rule.time_count <= type) {
+ if (time_zone_rule.type_count <= type) {
return {};
}
if (time_zone_rule.types[index] != 0) {
@@ -624,16 +635,109 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
std::array<char, time_zone_name_max> name{};
std::memcpy(name.data(), temp_name.data() + 1, std::size_t(bytes_read - 1));
+ // Fill in computed transition times with temp rule
TimeZoneRule temp_rule;
if (ParsePosixName(name.data(), temp_rule)) {
- UNIMPLEMENTED();
+ int have_abbreviation = 0;
+ int char_count = time_zone_rule.char_count;
+
+ for (int i = 0; i < temp_rule.type_count; i++) {
+ char* temp_abbreviation =
+ temp_rule.chars.data() + temp_rule.ttis[i].abbreviation_list_index;
+ int j;
+ for (j = 0; j < char_count; j++) {
+ if (std::strcmp(time_zone_rule.chars.data() + j, temp_abbreviation) == 0) {
+ temp_rule.ttis[i].abbreviation_list_index = j;
+ have_abbreviation++;
+ break;
+ }
+ }
+ if (j >= char_count) {
+ int temp_abbreviation_length = static_cast<int>(std::strlen(temp_abbreviation));
+ if (j + temp_abbreviation_length < time_zone_max_chars) {
+ std::strcpy(time_zone_rule.chars.data() + j, temp_abbreviation);
+ char_count = j + temp_abbreviation_length + 1;
+ temp_rule.ttis[i].abbreviation_list_index = j;
+ have_abbreviation++;
+ }
+ }
+ }
+
+ if (have_abbreviation == temp_rule.type_count) {
+ time_zone_rule.char_count = char_count;
+
+ // Original comment:
+ /* Ignore any trailing, no-op transitions generated
+ by zic as they don't help here and can run afoul
+ of bugs in zic 2016j or earlier. */
+ // This is possibly unnecessary for yuzu, since Nintendo doesn't run zic
+ while (1 < time_zone_rule.time_count &&
+ (time_zone_rule.types[time_zone_rule.time_count - 1] ==
+ time_zone_rule.types[time_zone_rule.time_count - 2])) {
+ time_zone_rule.time_count--;
+ }
+
+ for (int i = 0;
+ i < temp_rule.time_count && time_zone_rule.time_count < time_zone_max_times;
+ i++) {
+ const s64 transition_time = temp_rule.ats[i];
+ if (0 < time_zone_rule.time_count &&
+ transition_time <= time_zone_rule.ats[time_zone_rule.time_count - 1]) {
+ continue;
+ }
+
+ time_zone_rule.ats[time_zone_rule.time_count] = transition_time;
+ time_zone_rule.types[time_zone_rule.time_count] =
+ static_cast<s8>(time_zone_rule.type_count + temp_rule.types[i]);
+ time_zone_rule.time_count++;
+ }
+ for (int i = 0; i < temp_rule.type_count; i++) {
+ time_zone_rule.ttis[time_zone_rule.type_count++] = temp_rule.ttis[i];
+ }
+ }
}
}
+
+ const auto typesequiv = [](TimeZoneRule& rule, int a, int b) -> bool {
+ if (a < 0 || a >= rule.type_count || b < 0 || b >= rule.type_count) {
+ return {};
+ }
+
+ const struct TimeTypeInfo* ap = &rule.ttis[a];
+ const struct TimeTypeInfo* bp = &rule.ttis[b];
+
+ return (ap->gmt_offset == bp->gmt_offset && ap->is_dst == bp->is_dst &&
+ (std::strcmp(&rule.chars[ap->abbreviation_list_index],
+ &rule.chars[bp->abbreviation_list_index]) == 0));
+ };
+
if (time_zone_rule.type_count == 0) {
return {};
}
if (time_zone_rule.time_count > 1) {
- UNIMPLEMENTED();
+ if (time_zone_rule.ats[0] <= std::numeric_limits<s64>::max() - seconds_per_repeat) {
+ s64 repeatat = time_zone_rule.ats[0] + seconds_per_repeat;
+ int repeatattype = time_zone_rule.types[0];
+ for (int i = 1; i < time_zone_rule.time_count; ++i) {
+ if (time_zone_rule.ats[i] == repeatat &&
+ typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
+ time_zone_rule.go_back = true;
+ break;
+ }
+ }
+ }
+ if (std::numeric_limits<s64>::min() + seconds_per_repeat <=
+ time_zone_rule.ats[time_zone_rule.time_count - 1]) {
+ s64 repeatat = time_zone_rule.ats[time_zone_rule.time_count - 1] - seconds_per_repeat;
+ int repeatattype = time_zone_rule.types[time_zone_rule.time_count - 1];
+ for (int i = time_zone_rule.time_count; i >= 0; --i) {
+ if (time_zone_rule.ats[i] == repeatat &&
+ typesequiv(time_zone_rule, time_zone_rule.types[i], repeatattype)) {
+ time_zone_rule.go_ahead = true;
+ break;
+ }
+ }
+ }
}
s32 default_type{};
@@ -745,8 +849,9 @@ static Result CreateCalendarTime(s64 time, int gmt_offset, CalendarTimeInternal&
static Result ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
CalendarTimeInternal& calendar_time,
CalendarAdditionalInfo& calendar_additional_info) {
- if ((rules.go_ahead && time < rules.ats[0]) ||
- (rules.go_back && time > rules.ats[rules.time_count - 1])) {
+ ASSERT(rules.go_ahead ? rules.time_count > 0 : true);
+ if ((rules.go_back && time < rules.ats[0]) ||
+ (rules.go_ahead && time > rules.ats[rules.time_count - 1])) {
s64 seconds{};
if (time < rules.ats[0]) {
seconds = rules.ats[0] - time;
@@ -806,9 +911,13 @@ static Result ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
calendar_additional_info.is_dst = rules.ttis[tti_index].is_dst;
const char* time_zone{&rules.chars[rules.ttis[tti_index].abbreviation_list_index]};
- for (int index{}; time_zone[index] != '\0'; ++index) {
+ u32 index;
+ for (index = 0; time_zone[index] != '\0' && time_zone[index] != ',' &&
+ index < calendar_additional_info.timezone_name.size() - 1;
+ ++index) {
calendar_additional_info.timezone_name[index] = time_zone[index];
}
+ calendar_additional_info.timezone_name[index] = '\0';
return ResultSuccess;
}
@@ -1038,4 +1147,36 @@ Result TimeZoneManager::GetDeviceLocationName(LocationName& value) const {
return ResultSuccess;
}
+Result TimeZoneManager::GetTotalLocationNameCount(s32& count) const {
+ if (!is_initialized) {
+ return ERROR_UNINITIALIZED_CLOCK;
+ }
+ count = static_cast<u32>(total_location_name_count);
+
+ return ResultSuccess;
+}
+
+Result TimeZoneManager::GetTimeZoneRuleVersion(u128& version) const {
+ if (!is_initialized) {
+ return ERROR_UNINITIALIZED_CLOCK;
+ }
+ version = time_zone_rule_version;
+
+ return ResultSuccess;
+}
+
+Result TimeZoneManager::LoadLocationNameList(std::vector<LocationName>& values) const {
+ if (!is_initialized) {
+ return ERROR_UNINITIALIZED_CLOCK;
+ }
+
+ for (const auto& name : total_location_names) {
+ LocationName entry{};
+ std::memcpy(entry.data(), name.c_str(), name.size());
+ values.push_back(entry);
+ }
+
+ return ResultSuccess;
+}
+
} // namespace Service::Time::TimeZone
diff --git a/src/core/hle/service/time/time_zone_manager.h b/src/core/hle/service/time/time_zone_manager.h
index 5ebd4035e..8664f28d1 100644
--- a/src/core/hle/service/time/time_zone_manager.h
+++ b/src/core/hle/service/time/time_zone_manager.h
@@ -21,6 +21,10 @@ public:
total_location_name_count = value;
}
+ void SetLocationNames(std::vector<std::string> location_names) {
+ total_location_names = location_names;
+ }
+
void SetTimeZoneRuleVersion(const u128& value) {
time_zone_rule_version = value;
}
@@ -33,6 +37,9 @@ public:
FileSys::VirtualFile& vfs_file);
Result SetUpdatedTime(const Clock::SteadyClockTimePoint& value);
Result GetDeviceLocationName(TimeZone::LocationName& value) const;
+ Result GetTotalLocationNameCount(s32& count) const;
+ Result GetTimeZoneRuleVersion(u128& version) const;
+ Result LoadLocationNameList(std::vector<TimeZone::LocationName>& values) const;
Result ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const;
Result ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const;
Result ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const;
@@ -46,6 +53,7 @@ private:
std::string device_location_name{"GMT"};
u128 time_zone_rule_version{};
std::size_t total_location_name_count{};
+ std::vector<std::string> total_location_names{};
Clock::SteadyClockTimePoint time_zone_update_time_point{
Clock::SteadyClockTimePoint::GetRandom()};
};
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index cda8d8343..8171c82a5 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -15,10 +15,10 @@ ITimeZoneService::ITimeZoneService(Core::System& system_,
static const FunctionInfo functions[] = {
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
{1, nullptr, "SetDeviceLocationName"},
- {2, nullptr, "GetTotalLocationNameCount"},
- {3, nullptr, "LoadLocationNameList"},
+ {2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
+ {3, &ITimeZoneService::LoadLocationNameList, "LoadLocationNameList"},
{4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
- {5, nullptr, "GetTimeZoneRuleVersion"},
+ {5, &ITimeZoneService::GetTimeZoneRuleVersion, "GetTimeZoneRuleVersion"},
{6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
@@ -45,6 +45,57 @@ void ITimeZoneService::GetDeviceLocationName(HLERequestContext& ctx) {
rb.PushRaw(location_name);
}
+void ITimeZoneService::GetTotalLocationNameCount(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
+ s32 count{};
+ if (const Result result{
+ time_zone_content_manager.GetTimeZoneManager().GetTotalLocationNameCount(count)};
+ result != ResultSuccess) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(count);
+}
+
+void ITimeZoneService::LoadLocationNameList(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
+ std::vector<TimeZone::LocationName> location_names{};
+ if (const Result result{
+ time_zone_content_manager.GetTimeZoneManager().LoadLocationNameList(location_names)};
+ result != ResultSuccess) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ return;
+ }
+
+ ctx.WriteBuffer(location_names);
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(static_cast<s32>(location_names.size()));
+}
+void ITimeZoneService::GetTimeZoneRuleVersion(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Time, "called");
+
+ u128 rule_version{};
+ if (const Result result{
+ time_zone_content_manager.GetTimeZoneManager().GetTimeZoneRuleVersion(rule_version)};
+ result != ResultSuccess) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 6};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(rule_version);
+}
+
void ITimeZoneService::LoadTimeZoneRule(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()};
@@ -61,20 +112,14 @@ void ITimeZoneService::LoadTimeZoneRule(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called, location_name={}", location_name);
TimeZone::TimeZoneRule time_zone_rule{};
- if (const Result result{
- time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)};
- result != ResultSuccess) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- return;
- }
+ const Result result{time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)};
std::vector<u8> time_zone_rule_outbuffer(sizeof(TimeZone::TimeZoneRule));
std::memcpy(time_zone_rule_outbuffer.data(), &time_zone_rule, sizeof(TimeZone::TimeZoneRule));
ctx.WriteBuffer(time_zone_rule_outbuffer);
IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
+ rb.Push(result);
}
void ITimeZoneService::ToCalendarTime(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/time/time_zone_service.h b/src/core/hle/service/time/time_zone_service.h
index ea83b5714..952fcb0e2 100644
--- a/src/core/hle/service/time/time_zone_service.h
+++ b/src/core/hle/service/time/time_zone_service.h
@@ -22,6 +22,9 @@ public:
private:
void GetDeviceLocationName(HLERequestContext& ctx);
+ void GetTotalLocationNameCount(HLERequestContext& ctx);
+ void LoadLocationNameList(HLERequestContext& ctx);
+ void GetTimeZoneRuleVersion(HLERequestContext& ctx);
void LoadTimeZoneRule(HLERequestContext& ctx);
void ToCalendarTime(HLERequestContext& ctx);
void ToCalendarTimeWithMyRule(HLERequestContext& ctx);