summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/file_sys/patch_manager.cpp49
-rw-r--r--src/core/gdbstub/gdbstub.cpp123
-rw-r--r--src/core/hle/service/am/am.cpp12
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp5
-rw-r--r--src/core/hle/service/filesystem/filesystem.h1
-rw-r--r--src/core/hle/service/sm/sm.cpp54
-rw-r--r--src/core/hle/service/sm/sm.h3
-rw-r--r--src/core/hle/service/vi/vi.cpp32
-rw-r--r--src/core/settings.h1
9 files changed, 226 insertions, 54 deletions
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 8d062eb3e..e8df08724 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -26,6 +26,11 @@ namespace FileSys {
constexpr u64 SINGLE_BYTE_MODULUS = 0x100;
constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000;
+constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{
+ "main", "main.npdm", "rtld", "sdk", "subsdk0", "subsdk1", "subsdk2",
+ "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "subsdk8", "subsdk9",
+};
+
struct NSOBuildHeader {
u32_le magic;
INSERT_PADDING_BYTES(0x3C);
@@ -57,6 +62,15 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
if (exefs == nullptr)
return exefs;
+ if (Settings::values.dump_exefs) {
+ LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id);
+ const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id);
+ if (dump_dir != nullptr) {
+ const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs");
+ VfsRawCopyD(exefs, exefs_dir);
+ }
+ }
+
const auto installed = Service::FileSystem::GetUnionContents();
// Game Updates
@@ -70,6 +84,30 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
exefs = update->GetExeFS();
}
+ // LayeredExeFS
+ const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);
+ if (load_dir != nullptr && load_dir->GetSize() > 0) {
+ auto patch_dirs = load_dir->GetSubdirectories();
+ std::sort(
+ patch_dirs.begin(), patch_dirs.end(),
+ [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
+
+ std::vector<VirtualDir> layers;
+ layers.reserve(patch_dirs.size() + 1);
+ for (const auto& subdir : patch_dirs) {
+ auto exefs_dir = subdir->GetSubdirectory("exefs");
+ if (exefs_dir != nullptr)
+ layers.push_back(std::move(exefs_dir));
+ }
+ layers.push_back(exefs);
+
+ auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers));
+ if (layered != nullptr) {
+ LOG_INFO(Loader, " ExeFS: LayeredExeFS patches applied successfully");
+ exefs = std::move(layered);
+ }
+ }
+
return exefs;
}
@@ -314,18 +352,25 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam
if (IsDirValidAndNonEmpty(exefs_dir)) {
bool ips = false;
bool ipswitch = false;
+ bool layeredfs = false;
for (const auto& file : exefs_dir->GetFiles()) {
- if (file->GetExtension() == "ips")
+ if (file->GetExtension() == "ips") {
ips = true;
- else if (file->GetExtension() == "pchtxt")
+ } else if (file->GetExtension() == "pchtxt") {
ipswitch = true;
+ } else if (std::find(EXEFS_FILE_NAMES.begin(), EXEFS_FILE_NAMES.end(),
+ file->GetName()) != EXEFS_FILE_NAMES.end()) {
+ layeredfs = true;
+ }
}
if (ips)
AppendCommaIfNotEmpty(types, "IPS");
if (ipswitch)
AppendCommaIfNotEmpty(types, "IPSwitch");
+ if (layeredfs)
+ AppendCommaIfNotEmpty(types, "LayeredExeFS");
}
if (IsDirValidAndNonEmpty(mod->GetSubdirectory("romfs")))
AppendCommaIfNotEmpty(types, "LayeredFS");
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index bdcc889e0..687dea409 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -71,10 +71,6 @@ constexpr u32 PSTATE_REGISTER = 33;
constexpr u32 UC_ARM64_REG_Q0 = 34;
constexpr u32 FPCR_REGISTER = 66;
-// TODO/WiP - Used while working on support for FPU
-constexpr u32 TODO_DUMMY_REG_997 = 997;
-constexpr u32 TODO_DUMMY_REG_998 = 998;
-
// For sample XML files see the GDB source /gdb/features
// GDB also wants the l character at the start
// This XML defines what the registers are for this specific ARM device
@@ -260,6 +256,36 @@ static void RegWrite(std::size_t id, u64 val, Kernel::Thread* thread = nullptr)
}
}
+static u128 FpuRead(std::size_t id, Kernel::Thread* thread = nullptr) {
+ if (!thread) {
+ return u128{0};
+ }
+
+ auto& thread_context = thread->GetContext();
+
+ if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
+ return thread_context.vector_registers[id - UC_ARM64_REG_Q0];
+ } else if (id == FPCR_REGISTER) {
+ return u128{thread_context.fpcr, 0};
+ } else {
+ return u128{0};
+ }
+}
+
+static void FpuWrite(std::size_t id, u128 val, Kernel::Thread* thread = nullptr) {
+ if (!thread) {
+ return;
+ }
+
+ auto& thread_context = thread->GetContext();
+
+ if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
+ thread_context.vector_registers[id - UC_ARM64_REG_Q0] = val;
+ } else if (id == FPCR_REGISTER) {
+ thread_context.fpcr = val[0];
+ }
+}
+
/**
* Turns hex string character into the equivalent byte.
*
@@ -409,6 +435,27 @@ static u64 GdbHexToLong(const u8* src) {
return output;
}
+/**
+ * Convert a gdb-formatted hex string into a u128.
+ *
+ * @param src Pointer to hex string.
+ */
+static u128 GdbHexToU128(const u8* src) {
+ u128 output;
+
+ for (int i = 0; i < 16; i += 2) {
+ output[0] = (output[0] << 4) | HexCharToValue(src[15 - i - 1]);
+ output[0] = (output[0] << 4) | HexCharToValue(src[15 - i]);
+ }
+
+ for (int i = 0; i < 16; i += 2) {
+ output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i - 1]);
+ output[1] = (output[1] << 4) | HexCharToValue(src[16 + 15 - i]);
+ }
+
+ return output;
+}
+
/// Read a byte from the gdb client.
static u8 ReadByte() {
u8 c;
@@ -599,8 +646,7 @@ static void HandleQuery() {
for (u32 core = 0; core < Core::NUM_CPU_CORES; core++) {
const auto& threads = Core::System::GetInstance().Scheduler(core).GetThreadList();
for (const auto& thread : threads) {
- val += fmt::format("{:x}", thread->GetThreadID());
- val += ",";
+ val += fmt::format("{:x},", thread->GetThreadID());
}
}
val.pop_back();
@@ -791,11 +837,15 @@ static void ReadRegister() {
} else if (id == PSTATE_REGISTER) {
IntToGdbHex(reply, static_cast<u32>(RegRead(id, current_thread)));
} else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
- LongToGdbHex(reply, RegRead(id, current_thread));
+ u128 r = FpuRead(id, current_thread);
+ LongToGdbHex(reply, r[0]);
+ LongToGdbHex(reply + 16, r[1]);
} else if (id == FPCR_REGISTER) {
- LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_998, current_thread));
- } else {
- LongToGdbHex(reply, RegRead(TODO_DUMMY_REG_997, current_thread));
+ u128 r = FpuRead(id, current_thread);
+ IntToGdbHex(reply, static_cast<u32>(r[0]));
+ } else if (id == FPCR_REGISTER + 1) {
+ u128 r = FpuRead(id, current_thread);
+ IntToGdbHex(reply, static_cast<u32>(r[0] >> 32));
}
SendReply(reinterpret_cast<char*>(reply));
@@ -822,13 +872,18 @@ static void ReadRegisters() {
bufptr += 8;
- for (u32 reg = UC_ARM64_REG_Q0; reg <= UC_ARM64_REG_Q0 + 31; reg++) {
- LongToGdbHex(bufptr + reg * 16, RegRead(reg, current_thread));
+ u128 r;
+
+ for (u32 reg = UC_ARM64_REG_Q0; reg < FPCR_REGISTER; reg++) {
+ r = FpuRead(reg, current_thread);
+ LongToGdbHex(bufptr + reg * 32, r[0]);
+ LongToGdbHex(bufptr + reg * 32 + 16, r[1]);
}
bufptr += 32 * 32;
- LongToGdbHex(bufptr, RegRead(TODO_DUMMY_REG_998, current_thread));
+ r = FpuRead(FPCR_REGISTER, current_thread);
+ IntToGdbHex(bufptr, static_cast<u32>(r[0]));
bufptr += 8;
@@ -853,14 +908,12 @@ static void WriteRegister() {
} else if (id == PSTATE_REGISTER) {
RegWrite(id, GdbHexToInt(buffer_ptr), current_thread);
} else if (id >= UC_ARM64_REG_Q0 && id < FPCR_REGISTER) {
- RegWrite(id, GdbHexToLong(buffer_ptr), current_thread);
+ FpuWrite(id, GdbHexToU128(buffer_ptr), current_thread);
} else if (id == FPCR_REGISTER) {
- RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr), current_thread);
- } else {
- RegWrite(TODO_DUMMY_REG_997, GdbHexToLong(buffer_ptr), current_thread);
+ } else if (id == FPCR_REGISTER + 1) {
}
- // Update Unicorn context skipping scheduler, no running threads at this point
+ // Update ARM context, skipping scheduler - no running threads at this point
Core::System::GetInstance()
.ArmInterface(current_core)
.LoadContext(current_thread->GetContext());
@@ -885,13 +938,13 @@ static void WriteRegisters() {
} else if (reg >= UC_ARM64_REG_Q0 && reg < FPCR_REGISTER) {
RegWrite(reg, GdbHexToLong(buffer_ptr + i * 16), current_thread);
} else if (reg == FPCR_REGISTER) {
- RegWrite(TODO_DUMMY_REG_998, GdbHexToLong(buffer_ptr + i * 16), current_thread);
- } else {
- UNIMPLEMENTED();
+ RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
+ } else if (reg == FPCR_REGISTER + 1) {
+ RegWrite(FPCR_REGISTER, GdbHexToLong(buffer_ptr + i * 16), current_thread);
}
}
- // Update Unicorn context skipping scheduler, no running threads at this point
+ // Update ARM context, skipping scheduler - no running threads at this point
Core::System::GetInstance()
.ArmInterface(current_core)
.LoadContext(current_thread->GetContext());
@@ -917,12 +970,6 @@ static void ReadMemory() {
SendReply("E01");
}
- const auto& vm_manager = Core::CurrentProcess()->VMManager();
- if (addr < vm_manager.GetCodeRegionBaseAddress() ||
- addr >= vm_manager.GetMapRegionEndAddress()) {
- return SendReply("E00");
- }
-
if (!Memory::IsValidVirtualAddress(addr)) {
return SendReply("E00");
}
@@ -967,7 +1014,7 @@ void Break(bool is_memory_break) {
static void Step() {
if (command_length > 1) {
RegWrite(PC_REGISTER, GdbHexToLong(command_buffer + 1), current_thread);
- // Update Unicorn context skipping scheduler, no running threads at this point
+ // Update ARM context, skipping scheduler - no running threads at this point
Core::System::GetInstance()
.ArmInterface(current_core)
.LoadContext(current_thread->GetContext());
@@ -1010,7 +1057,7 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
breakpoint.addr = addr;
breakpoint.len = len;
Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size());
- static constexpr std::array<u8, 4> btrap{{0x00, 0x7d, 0x20, 0xd4}};
+ static constexpr std::array<u8, 4> btrap{0x00, 0x7d, 0x20, 0xd4};
Memory::WriteBlock(addr, btrap.data(), btrap.size());
Core::System::GetInstance().InvalidateCpuInstructionCaches();
p.insert({addr, breakpoint});
@@ -1321,13 +1368,15 @@ void SetCpuStepFlag(bool is_step) {
}
void SendTrap(Kernel::Thread* thread, int trap) {
- if (send_trap) {
- if (!halt_loop || current_thread == thread) {
- current_thread = thread;
- SendSignal(thread, trap);
- }
- halt_loop = true;
- send_trap = false;
+ if (!send_trap) {
+ return;
}
+
+ if (!halt_loop || current_thread == thread) {
+ current_thread = thread;
+ SendSignal(thread, trap);
+ }
+ halt_loop = true;
+ send_trap = false;
}
}; // namespace GDBStub
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index f4127701f..4f17b52f9 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -483,11 +483,15 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode) {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
+ static_cast<u32>(Settings::values.resolution_factor));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
+ static_cast<u32>(Settings::values.resolution_factor));
} else {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
+ static_cast<u32>(Settings::values.resolution_factor));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
+ static_cast<u32>(Settings::values.resolution_factor));
}
LOG_DEBUG(Service_AM, "called");
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 5d6294016..2aa77f68d 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -341,6 +341,10 @@ std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() {
return registered_cache_union;
}
+void ClearUnionContents() {
+ registered_cache_union = nullptr;
+}
+
FileSys::RegisteredCache* GetSystemNANDContents() {
LOG_TRACE(Service_FS, "Opening System NAND Contents");
@@ -391,6 +395,7 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
bis_factory = nullptr;
save_data_factory = nullptr;
sdmc_factory = nullptr;
+ ClearUnionContents();
}
auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index ff9182e84..0a6cb6635 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -49,6 +49,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space)
ResultVal<FileSys::VirtualDir> OpenSDMC();
std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents();
+void ClearUnionContents();
FileSys::RegisteredCache* GetSystemNANDContents();
FileSys::RegisteredCache* GetUserNANDContents();
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 464e79d01..c1b2f33b9 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -63,6 +63,17 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService
return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port));
}
+ResultCode ServiceManager::UnregisterService(std::string name) {
+ CASCADE_CODE(ValidateServiceName(name));
+
+ const auto iter = registered_services.find(name);
+ if (iter == registered_services.end())
+ return ERR_SERVICE_NOT_REGISTERED;
+
+ registered_services.erase(iter);
+ return RESULT_SUCCESS;
+}
+
ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> ServiceManager::GetServicePort(
const std::string& name) {
@@ -127,13 +138,52 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
}
}
+void SM::RegisterService(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ const auto name_buf = rp.PopRaw<std::array<char, 8>>();
+ const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
+
+ const std::string name(name_buf.begin(), end);
+
+ const auto unk_bool = static_cast<bool>(rp.PopRaw<u32>());
+ const auto session_count = rp.PopRaw<u32>();
+
+ LOG_DEBUG(Service_SM, "called with unk_bool={}", unk_bool);
+
+ auto handle = service_manager->RegisterService(name, session_count);
+ if (handle.Failed()) {
+ LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}",
+ handle.Code().raw);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(handle.Code());
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
+ rb.Push(handle.Code());
+ rb.PushMoveObjects(std::move(handle).Unwrap());
+}
+
+void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ const auto name_buf = rp.PopRaw<std::array<char, 8>>();
+ const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
+
+ const std::string name(name_buf.begin(), end);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(service_manager->UnregisterService(name));
+}
+
SM::SM(std::shared_ptr<ServiceManager> service_manager)
: ServiceFramework("sm:", 4), service_manager(std::move(service_manager)) {
static const FunctionInfo functions[] = {
{0x00000000, &SM::Initialize, "Initialize"},
{0x00000001, &SM::GetService, "GetService"},
- {0x00000002, nullptr, "RegisterService"},
- {0x00000003, nullptr, "UnregisterService"},
+ {0x00000002, &SM::RegisterService, "RegisterService"},
+ {0x00000003, &SM::UnregisterService, "UnregisterService"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 4f8145dda..c4714b3e3 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -35,6 +35,8 @@ public:
private:
void Initialize(Kernel::HLERequestContext& ctx);
void GetService(Kernel::HLERequestContext& ctx);
+ void RegisterService(Kernel::HLERequestContext& ctx);
+ void UnregisterService(Kernel::HLERequestContext& ctx);
std::shared_ptr<ServiceManager> service_manager;
};
@@ -48,6 +50,7 @@ public:
ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name,
unsigned int max_sessions);
+ ResultCode UnregisterService(std::string name);
ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name);
ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ConnectToService(const std::string& name);
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index d25fdb1fe..a72416084 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -510,7 +510,11 @@ private:
if (transaction == TransactionId::Connect) {
IGBPConnectRequestParcel request{ctx.ReadBuffer()};
- IGBPConnectResponseParcel response{1280, 720};
+ IGBPConnectResponseParcel response{
+ static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) *
+ Settings::values.resolution_factor),
+ static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) *
+ Settings::values.resolution_factor)};
ctx.WriteBuffer(response.Serialize());
} else if (transaction == TransactionId::SetPreallocatedBuffer) {
IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()};
@@ -692,11 +696,15 @@ private:
rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode) {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
+ static_cast<u32>(Settings::values.resolution_factor));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
+ static_cast<u32>(Settings::values.resolution_factor));
} else {
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
+ static_cast<u32>(Settings::values.resolution_factor));
+ rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
+ static_cast<u32>(Settings::values.resolution_factor));
}
rb.PushRaw<float>(60.0f);
@@ -901,11 +909,15 @@ private:
rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode) {
- rb.Push(static_cast<u64>(DisplayResolution::DockedWidth));
- rb.Push(static_cast<u64>(DisplayResolution::DockedHeight));
+ rb.Push(static_cast<u64>(DisplayResolution::DockedWidth) *
+ static_cast<u32>(Settings::values.resolution_factor));
+ rb.Push(static_cast<u64>(DisplayResolution::DockedHeight) *
+ static_cast<u32>(Settings::values.resolution_factor));
} else {
- rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth));
- rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight));
+ rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth) *
+ static_cast<u32>(Settings::values.resolution_factor));
+ rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight) *
+ static_cast<u32>(Settings::values.resolution_factor));
}
}
@@ -922,6 +934,8 @@ private:
void ListDisplays(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
DisplayInfo display_info;
+ display_info.width *= static_cast<u64>(Settings::values.resolution_factor);
+ display_info.height *= static_cast<u64>(Settings::values.resolution_factor);
ctx.WriteBuffer(&display_info, sizeof(DisplayInfo));
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
diff --git a/src/core/settings.h b/src/core/settings.h
index e63134f80..a0c5fd447 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -403,6 +403,7 @@ struct Values {
bool use_gdbstub;
u16 gdbstub_port;
std::string program_args;
+ bool dump_exefs;
bool dump_nso;
// WebService