mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-08 13:11:02 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1e5532cde |
@@ -858,7 +858,7 @@ struct Values {
|
||||
SwitchableSetting<std::string> program_args{linkage,
|
||||
std::string(),
|
||||
"program_args",
|
||||
Category::System,
|
||||
Category::Debugging,
|
||||
Specialization::Default,
|
||||
true, // save_ - persist in config file
|
||||
false}; // runtime_modifiable_ - startup-only
|
||||
@@ -904,7 +904,7 @@ struct Values {
|
||||
0,
|
||||
65535,
|
||||
"debug_knobs",
|
||||
Category::System,
|
||||
Category::Debugging,
|
||||
Specialization::Countable,
|
||||
true,
|
||||
true};
|
||||
|
||||
@@ -139,7 +139,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||
{405, nullptr, "ListApplicationControlCacheEntryInfo"},
|
||||
{406, nullptr, "GetApplicationControlProperty"},
|
||||
{407, &IApplicationManagerInterface::ListApplicationTitle, "ListApplicationTitle"},
|
||||
{408, &IApplicationManagerInterface::ListApplicationIcon, "ListApplicationIcon"},
|
||||
{408, nullptr, "ListApplicationIcon"},
|
||||
{411, nullptr, "Unknown411"}, //19.0.0+
|
||||
{412, nullptr, "Unknown412"}, //19.0.0+
|
||||
{413, nullptr, "Unknown413"}, //19.0.0+
|
||||
@@ -894,9 +894,4 @@ void IApplicationManagerInterface::ListApplicationTitle(HLERequestContext& ctx)
|
||||
IReadOnlyApplicationControlDataInterface(system).ListApplicationTitle(ctx);
|
||||
}
|
||||
|
||||
void IApplicationManagerInterface::ListApplicationIcon(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
IReadOnlyApplicationControlDataInterface(system).ListApplicationIcon(ctx);
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
||||
|
||||
@@ -78,7 +78,6 @@ public:
|
||||
|
||||
void PushApplicationRecord(HLERequestContext& ctx);
|
||||
void ListApplicationTitle(HLERequestContext& ctx);
|
||||
void ListApplicationIcon(HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
@@ -10,17 +10,13 @@
|
||||
#include <string>
|
||||
|
||||
#include "common/stb.h"
|
||||
#include "common/logging.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/vfs/vfs.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/ns/ns_results.h"
|
||||
@@ -76,26 +72,24 @@ void SanitizeJPEGImageSize(std::vector<u8>& image) {
|
||||
|
||||
// IAsyncValue implementation for ListApplicationTitle
|
||||
// https://switchbrew.org/wiki/NS_services#ListApplicationTitle
|
||||
class IAsyncValue final : public ServiceFramework<IAsyncValue> {
|
||||
class IAsyncValueForListApplicationTitle final : public ServiceFramework<IAsyncValueForListApplicationTitle> {
|
||||
public:
|
||||
explicit IAsyncValue(Core::System& system_, s32 offset, s32 size)
|
||||
: ServiceFramework{system_, "IAsyncValue"}
|
||||
, service_context{system_, "IAsyncValue"}
|
||||
, data_offset{offset}
|
||||
, data_size{size}
|
||||
{
|
||||
explicit IAsyncValueForListApplicationTitle(Core::System& system_, s32 offset, s32 size)
|
||||
: ServiceFramework{system_, "IAsyncValue"}, service_context{system_, "IAsyncValue"},
|
||||
data_offset{offset}, data_size{size} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IAsyncValue::GetSize>, "GetSize"},
|
||||
{1, D<&IAsyncValue::Get>, "Get"},
|
||||
{2, D<&IAsyncValue::Cancel>, "Cancel"},
|
||||
{3, D<&IAsyncValue::GetErrorContext>, "GetErrorContext"},
|
||||
{0, &IAsyncValueForListApplicationTitle::GetSize, "GetSize"},
|
||||
{1, &IAsyncValueForListApplicationTitle::Get, "Get"},
|
||||
{2, &IAsyncValueForListApplicationTitle::Cancel, "Cancel"},
|
||||
{3, &IAsyncValueForListApplicationTitle::GetErrorContext, "GetErrorContext"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
completion_event = service_context.CreateEvent("IAsyncValue:Completion");
|
||||
completion_event->GetReadableEvent().Signal(system.Kernel());
|
||||
}
|
||||
|
||||
~IAsyncValue() override {
|
||||
~IAsyncValueForListApplicationTitle() override {
|
||||
service_context.CloseEvent(completion_event);
|
||||
}
|
||||
|
||||
@@ -104,24 +98,35 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Result GetSize(Out<s64> out_data_size) {
|
||||
void GetSize(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_data_size = data_size;
|
||||
R_SUCCEED();
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<s64>(data_size);
|
||||
}
|
||||
Result Get(OutBuffer<BufferAttr_HipcMapAlias> out_data_offset) {
|
||||
|
||||
void Get(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
std::memcpy(out_data_offset.data(), &data_offset, sizeof(s32));
|
||||
R_SUCCEED();
|
||||
std::vector<u8> buffer(sizeof(s32));
|
||||
std::memcpy(buffer.data(), &data_offset, sizeof(s32));
|
||||
ctx.WriteBuffer(buffer);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
Result Cancel() {
|
||||
|
||||
void Cancel(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_SUCCEED();
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
Result GetErrorContext() {
|
||||
|
||||
void GetErrorContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_SUCCEED();
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* completion_event{};
|
||||
s32 data_offset;
|
||||
@@ -139,7 +144,6 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
|
||||
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
||||
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData2>, "GetApplicationControlData"},
|
||||
{10, &IReadOnlyApplicationControlDataInterface::ListApplicationIcon, "ListApplicationIcon"},
|
||||
{13, &IReadOnlyApplicationControlDataInterface::ListApplicationTitle, "ListApplicationTitle"},
|
||||
{19, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData3>, "GetApplicationControlData"},
|
||||
};
|
||||
@@ -156,7 +160,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
|
||||
application_control_source, application_id);
|
||||
|
||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
const auto size = out_buffer.size();
|
||||
|
||||
@@ -164,7 +169,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||
const auto total_size = sizeof(FileSys::RawNACP) + icon_size;
|
||||
|
||||
if (size < total_size) {
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size);
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
|
||||
size);
|
||||
R_THROW(ResultUnknown);
|
||||
}
|
||||
|
||||
@@ -172,7 +178,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||
const auto bytes = control.first->GetRawBytes();
|
||||
std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
|
||||
} else {
|
||||
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero", application_id);
|
||||
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
|
||||
application_id);
|
||||
std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP));
|
||||
}
|
||||
|
||||
@@ -197,12 +204,15 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage(
|
||||
// Convert to application language, get priority list
|
||||
const auto application_language = ConvertToApplicationLanguage(language_code);
|
||||
if (application_language == std::nullopt) {
|
||||
LOG_ERROR(Service_NS, "Could not convert application language! language_code={}", language_code);
|
||||
LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
|
||||
language_code);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
|
||||
if (!priority_list) {
|
||||
LOG_ERROR(Service_NS, "Could not find application language priorities! application_language={}", *application_language);
|
||||
LOG_ERROR(Service_NS,
|
||||
"Could not find application language priorities! application_language={}",
|
||||
*application_language);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
|
||||
@@ -246,7 +256,8 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData2(
|
||||
const auto nacp_size = sizeof(FileSys::RawNACP);
|
||||
|
||||
if (size < nacp_size) {
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min={:08X})", size, nacp_size);
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min={:08X})",
|
||||
size, nacp_size);
|
||||
R_THROW(ResultUnknown);
|
||||
}
|
||||
|
||||
@@ -297,81 +308,63 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData2(
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IReadOnlyApplicationControlDataInterface::ListApplicationIcon(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NS, "(stubbed)");
|
||||
|
||||
void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) {
|
||||
/*
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto control_source = rp.PopRaw<u8>();
|
||||
rp.Skip(7, false);
|
||||
auto transfer_memory_size = rp.Pop<u64>();
|
||||
*/
|
||||
|
||||
const auto app_ids_buffer = ctx.ReadBuffer();
|
||||
const u64 app_count = app_ids_buffer.size() / sizeof(u64);
|
||||
const size_t app_count = app_ids_buffer.size() / sizeof(u64);
|
||||
|
||||
std::vector<u64> application_ids(app_count);
|
||||
if (app_count > 0) {
|
||||
std::memcpy(application_ids.data(), app_ids_buffer.data(), app_count * sizeof(u64));
|
||||
}
|
||||
|
||||
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
|
||||
auto* t_mem = t_mem_obj.GetPointerUnsafe();
|
||||
size_t out_length = 0;
|
||||
|
||||
constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry);
|
||||
const size_t total_data_size = app_count * title_entry_size;
|
||||
|
||||
constexpr s32 data_offset = 0;
|
||||
|
||||
if (t_mem != nullptr && t_mem->GetOwner() != nullptr && app_count > 0) {
|
||||
auto& memory = t_mem->GetOwner()->GetMemory();
|
||||
const auto t_mem_address = t_mem->GetSourceAddress();
|
||||
// u64 - app count
|
||||
memory.WriteBlock(t_mem_address + out_length, &app_count, sizeof(u64));
|
||||
out_length += sizeof(u64);
|
||||
// [list of u64] - size of icons
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
u64 full_size = control.second->GetSize();
|
||||
memory.WriteBlock(t_mem_address + out_length, &full_size, sizeof(u64));
|
||||
out_length += sizeof(u64);
|
||||
}
|
||||
// [list of raw icon data]
|
||||
std::vector<u8> full_icon_data;
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
auto const full_size = control.second->GetSize();
|
||||
if (full_size > 0) {
|
||||
full_icon_data.resize(full_size);
|
||||
control.second->Read(full_icon_data.data(), full_size, 0);
|
||||
memory.WriteBlock(t_mem_address + out_length, full_icon_data.data(), full_size);
|
||||
out_length += full_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto async_value = std::make_shared<IAsyncValue>(system, 0, s32(out_length));
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(ctx, async_value->ReadableEvent());
|
||||
rb.PushIpcInterface(ctx, std::move(async_value));
|
||||
}
|
||||
|
||||
void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) {
|
||||
const auto app_ids_buffer = ctx.ReadBuffer();
|
||||
const size_t app_count = app_ids_buffer.size() / sizeof(u64);
|
||||
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
|
||||
auto* t_mem = t_mem_obj.GetPointerUnsafe();
|
||||
constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry);
|
||||
const size_t total_data_size = app_count * title_entry_size;
|
||||
constexpr s32 data_offset = 0;
|
||||
if (t_mem != nullptr && app_count > 0) {
|
||||
auto& memory = system.ApplicationMemory();
|
||||
const auto t_mem_address = t_mem->GetSourceAddress();
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = app_ids_buffer[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||
const u64 app_id = application_ids[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
|
||||
FileSys::LanguageEntry entry{};
|
||||
if (control.first != nullptr) {
|
||||
entry = control.first->GetLanguageEntry();
|
||||
}
|
||||
|
||||
const size_t offset = i * title_entry_size;
|
||||
memory.WriteBlock(t_mem_address + offset, &entry, title_entry_size);
|
||||
}
|
||||
}
|
||||
auto async_value = std::make_shared<IAsyncValue>(system, data_offset, s32(total_data_size));
|
||||
|
||||
auto async_value = std::make_shared<IAsyncValueForListApplicationTitle>(
|
||||
system, data_offset, static_cast<s32>(total_data_size));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(ctx, async_value->ReadableEvent());
|
||||
rb.PushIpcInterface(ctx, std::move(async_value));
|
||||
}
|
||||
|
||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData3(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_flags_a, Out<u32> out_flags_b, Out<u32> out_actual_size, ApplicationControlSource application_control_source, u8 flag1, u8 flag2, u64 application_id) {
|
||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData3(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_flags_a, Out<u32> out_flags_b,
|
||||
Out<u32> out_actual_size, ApplicationControlSource application_control_source, u8 flag1, u8 flag2, u64 application_id) {
|
||||
LOG_INFO(Service_NS, "called with control_source={}, flags=({:02X},{:02X}), application_id={:016X}",
|
||||
application_control_source, flag1, flag2, application_id);
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ public:
|
||||
u8 flag1,
|
||||
u8 flag2,
|
||||
u64 application_id);
|
||||
void ListApplicationIcon(HLERequestContext& ctx);
|
||||
void ListApplicationTitle(HLERequestContext& ctx);
|
||||
Result GetApplicationControlData3(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
@@ -16,8 +16,10 @@ IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::S
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IReadOnlyApplicationRecordInterface::HasApplicationRecord>, "HasApplicationRecord"},
|
||||
{1, nullptr, "NotifyApplicationFailure"},
|
||||
{2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>, "IsDataCorruptedResult"},
|
||||
{3, D<&IReadOnlyApplicationRecordInterface::ListApplicationRecord>, "ListApplicationRecord"},
|
||||
{2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>,
|
||||
"IsDataCorruptedResult"},
|
||||
{3, D<&IReadOnlyApplicationRecordInterface::ListApplicationRecord>,
|
||||
"ListApplicationRecord"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -299,12 +299,17 @@ void Config::ReadDataStorageValues() {
|
||||
void Config::ReadDebuggingValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
||||
|
||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||
Settings::values.record_frame_times =
|
||||
ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false));
|
||||
if (global) {
|
||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||
Settings::values.record_frame_times =
|
||||
ReadBooleanSetting(std::string("record_frame_times"), std::make_optional(false));
|
||||
|
||||
ReadCategory(Settings::Category::Debugging);
|
||||
ReadCategory(Settings::Category::DebuggingGraphics);
|
||||
ReadCategory(Settings::Category::Debugging);
|
||||
ReadCategory(Settings::Category::DebuggingGraphics);
|
||||
} else {
|
||||
ReadSettingGeneric(&Settings::values.program_args);
|
||||
ReadSettingGeneric(&Settings::values.debug_knobs);
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
@@ -415,12 +420,12 @@ void Config::ReadLibraryAppletValues() {
|
||||
void Config::ReadValues() {
|
||||
if (global) {
|
||||
ReadDataStorageValues();
|
||||
ReadDebuggingValues();
|
||||
ReadDisabledAddOnValues();
|
||||
ReadServiceValues();
|
||||
ReadWebServiceValues();
|
||||
ReadMiscellaneousValues();
|
||||
}
|
||||
ReadDebuggingValues();
|
||||
ReadLibraryAppletValues();
|
||||
ReadNetworkValues();
|
||||
ReadControlValues();
|
||||
@@ -511,13 +516,13 @@ void Config::SaveValues() {
|
||||
if (global) {
|
||||
LOG_DEBUG(Config, "Saving global generic configuration values");
|
||||
SaveDataStorageValues();
|
||||
SaveDebuggingValues();
|
||||
SaveDisabledAddOnValues();
|
||||
SaveWebServiceValues();
|
||||
SaveMiscellaneousValues();
|
||||
} else {
|
||||
LOG_DEBUG(Config, "Saving only generic configuration values");
|
||||
}
|
||||
SaveDebuggingValues();
|
||||
SaveLibraryAppletValues();
|
||||
SaveNetworkValues();
|
||||
SaveControlValues();
|
||||
@@ -600,11 +605,16 @@ void Config::SaveDataStorageValues() {
|
||||
void Config::SaveDebuggingValues() {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Debugging));
|
||||
|
||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||
WriteBooleanSetting(std::string("record_frame_times"), Settings::values.record_frame_times);
|
||||
if (global) {
|
||||
// Intentionally not using the QT default setting as this is intended to be changed in the ini
|
||||
WriteBooleanSetting(std::string("record_frame_times"), Settings::values.record_frame_times);
|
||||
|
||||
WriteCategory(Settings::Category::Debugging);
|
||||
WriteCategory(Settings::Category::DebuggingGraphics);
|
||||
WriteCategory(Settings::Category::Debugging);
|
||||
WriteCategory(Settings::Category::DebuggingGraphics);
|
||||
} else {
|
||||
WriteSettingGeneric(&Settings::values.program_args);
|
||||
WriteSettingGeneric(&Settings::values.debug_knobs);
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user