Compare commits
26 Commits
android-78
...
android-81
Author | SHA1 | Date | |
---|---|---|---|
4ff5edbdd8 | |||
37a4a6751a | |||
93a1cd75fe | |||
b356909212 | |||
bb28f4a0c4 | |||
0993c71335 | |||
6e1b113c89 | |||
c46f54b091 | |||
3983ce9b5c | |||
d2cd08e3e1 | |||
bb4ae5ee53 | |||
ace91dd0c0 | |||
2921a24268 | |||
5269a46399 | |||
33e2dce715 | |||
f3bc7354b1 | |||
bd5ae33153 | |||
16f1592e50 | |||
fda08cbbb0 | |||
1e24d02434 | |||
a57ca3fb66 | |||
4f69be8169 | |||
b6ad7e263b | |||
4a59dc2947 | |||
d31676935e | |||
26658c2e93 |
@ -1,3 +1,11 @@
|
||||
| Pull Request | Commit | Title | Author | Merged? |
|
||||
|----|----|----|----|----|
|
||||
|
||||
|
||||
End of merge log. You can find the original README.md below the break.
|
||||
|
||||
-----
|
||||
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
@ -50,6 +50,7 @@ import org.yuzu.yuzu_emu.model.TaskViewModel
|
||||
import org.yuzu.yuzu_emu.utils.*
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
@ -639,7 +640,15 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
file.path.length
|
||||
)
|
||||
stream.putNextEntry(ZipEntry(newPath))
|
||||
stream.write(file.readBytes())
|
||||
|
||||
val buffer = ByteArray(8096)
|
||||
var read: Int
|
||||
FileInputStream(file).use { fis ->
|
||||
while (fis.read(buffer).also { read = it } != -1) {
|
||||
stream.write(buffer, 0, read)
|
||||
}
|
||||
}
|
||||
|
||||
stream.closeEntry()
|
||||
}
|
||||
}
|
||||
@ -664,7 +673,8 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
||||
checkStream.use { stream ->
|
||||
var ze: ZipEntry? = null
|
||||
while (stream.nextEntry?.also { ze = it } != null) {
|
||||
if (ze!!.name.trim() == "/config/config.ini") {
|
||||
val itemName = ze!!.name.trim()
|
||||
if (itemName == "/config/config.ini" || itemName == "config/config.ini") {
|
||||
isYuzuBackup = true
|
||||
return@use
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applet_ae.h"
|
||||
#include "core/hle/service/am/applet_oe.h"
|
||||
#include "core/hle/service/am/applets/applet_mii_edit_types.h"
|
||||
#include "core/hle/service/am/applets/applet_profile_select.h"
|
||||
#include "core/hle/service/am/applets/applet_web_browser.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
@ -190,7 +191,7 @@ IDisplayController::IDisplayController(Core::System& system_)
|
||||
{5, nullptr, "GetLastForegroundCaptureImageEx"},
|
||||
{6, nullptr, "GetLastApplicationCaptureImageEx"},
|
||||
{7, nullptr, "GetCallerAppletCaptureImageEx"},
|
||||
{8, nullptr, "TakeScreenShotOfOwnLayer"},
|
||||
{8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
|
||||
{9, nullptr, "CopyBetweenCaptureBuffers"},
|
||||
{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
|
||||
{11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
|
||||
@ -218,6 +219,13 @@ IDisplayController::IDisplayController(Core::System& system_)
|
||||
|
||||
IDisplayController::~IDisplayController() = default;
|
||||
|
||||
void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
IDebugFunctions::IDebugFunctions(Core::System& system_)
|
||||
: ServiceFramework{system_, "IDebugFunctions"} {
|
||||
// clang-format off
|
||||
@ -724,7 +732,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
||||
{110, nullptr, "OpenMyGpuErrorHandler"},
|
||||
{120, nullptr, "GetAppletLaunchedHistory"},
|
||||
{200, nullptr, "GetOperationModeSystemInfo"},
|
||||
{300, nullptr, "GetSettingsPlatformRegion"},
|
||||
{300, &ICommonStateGetter::GetSettingsPlatformRegion, "GetSettingsPlatformRegion"},
|
||||
{400, nullptr, "ActivateMigrationService"},
|
||||
{401, nullptr, "DeactivateMigrationService"},
|
||||
{500, nullptr, "DisableSleepTillShutdown"},
|
||||
@ -736,6 +744,10 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// Configure applets to be in foreground state
|
||||
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
|
||||
msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
|
||||
}
|
||||
|
||||
ICommonStateGetter::~ICommonStateGetter() = default;
|
||||
@ -867,6 +879,14 @@ void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(HLERequestContext&
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ICommonStateGetter::GetSettingsPlatformRegion(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(SysPlatformRegion::Global);
|
||||
}
|
||||
|
||||
void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
|
||||
HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
@ -1324,18 +1344,19 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
|
||||
|
||||
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
|
||||
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "PopInData"},
|
||||
{1, nullptr, "PushOutData"},
|
||||
{0, &ILibraryAppletSelfAccessor::PopInData, "PopInData"},
|
||||
{1, &ILibraryAppletSelfAccessor::PushOutData, "PushOutData"},
|
||||
{2, nullptr, "PopInteractiveInData"},
|
||||
{3, nullptr, "PushInteractiveOutData"},
|
||||
{5, nullptr, "GetPopInDataEvent"},
|
||||
{6, nullptr, "GetPopInteractiveInDataEvent"},
|
||||
{10, nullptr, "ExitProcessAndReturn"},
|
||||
{11, nullptr, "GetLibraryAppletInfo"},
|
||||
{10, &ILibraryAppletSelfAccessor::ExitProcessAndReturn, "ExitProcessAndReturn"},
|
||||
{11, &ILibraryAppletSelfAccessor::GetLibraryAppletInfo, "GetLibraryAppletInfo"},
|
||||
{12, nullptr, "GetMainAppletIdentityInfo"},
|
||||
{13, nullptr, "CanUseApplicationCore"},
|
||||
{14, nullptr, "GetCallerAppletIdentityInfo"},
|
||||
{14, &ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo, "GetCallerAppletIdentityInfo"},
|
||||
{15, nullptr, "GetMainAppletApplicationControlProperty"},
|
||||
{16, nullptr, "GetMainAppletStorageId"},
|
||||
{17, nullptr, "GetCallerAppletIdentityInfoStack"},
|
||||
@ -1361,10 +1382,142 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
|
||||
{140, nullptr, "SetApplicationMemoryReservation"},
|
||||
{150, nullptr, "ShouldSetGpuTimeSliceManually"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
||||
PushInShowMiiEditData();
|
||||
}
|
||||
|
||||
ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
|
||||
void ILibraryAppletSelfAccessor::PopInData(HLERequestContext& ctx) {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
if (queue_data.empty()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultNoDataInChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = queue_data.front();
|
||||
queue_data.pop_front();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IStorage>(system, std::move(data));
|
||||
}
|
||||
|
||||
void ILibraryAppletSelfAccessor::PushOutData(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ILibraryAppletSelfAccessor::ExitProcessAndReturn(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
system.Exit();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
|
||||
struct LibraryAppletInfo {
|
||||
Applets::AppletId applet_id;
|
||||
Applets::LibraryAppletMode library_applet_mode;
|
||||
};
|
||||
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
const LibraryAppletInfo applet_info{
|
||||
.applet_id = Applets::AppletId::MiiEdit,
|
||||
.library_applet_mode = Applets::LibraryAppletMode::AllForeground,
|
||||
};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(applet_info);
|
||||
}
|
||||
|
||||
void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext& ctx) {
|
||||
struct AppletIdentityInfo {
|
||||
Applets::AppletId applet_id;
|
||||
INSERT_PADDING_BYTES(0x4);
|
||||
u64 application_id;
|
||||
};
|
||||
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
const AppletIdentityInfo applet_info{
|
||||
.applet_id = Applets::AppletId::QLaunch,
|
||||
.application_id = 0x0100000000001000ull,
|
||||
};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 6};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(applet_info);
|
||||
}
|
||||
|
||||
void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
|
||||
struct MiiEditV3 {
|
||||
Applets::MiiEditAppletInputCommon common;
|
||||
Applets::MiiEditAppletInputV3 input;
|
||||
};
|
||||
static_assert(sizeof(MiiEditV3) == 0x100, "MiiEditV3 has incorrect size.");
|
||||
|
||||
MiiEditV3 mii_arguments{
|
||||
.common =
|
||||
{
|
||||
.version = Applets::MiiEditAppletVersion::Version3,
|
||||
.applet_mode = Applets::MiiEditAppletMode::ShowMiiEdit,
|
||||
},
|
||||
.input{},
|
||||
};
|
||||
|
||||
std::vector<u8> argument_data(sizeof(mii_arguments));
|
||||
std::memcpy(argument_data.data(), &mii_arguments, sizeof(mii_arguments));
|
||||
|
||||
queue_data.emplace_back(std::move(argument_data));
|
||||
}
|
||||
|
||||
IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
|
||||
: ServiceFramework{system_, "IAppletCommonFunctions"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "SetTerminateResult"},
|
||||
{10, nullptr, "ReadThemeStorage"},
|
||||
{11, nullptr, "WriteThemeStorage"},
|
||||
{20, nullptr, "PushToAppletBoundChannel"},
|
||||
{21, nullptr, "TryPopFromAppletBoundChannel"},
|
||||
{40, nullptr, "GetDisplayLogicalResolution"},
|
||||
{42, nullptr, "SetDisplayMagnification"},
|
||||
{50, nullptr, "SetHomeButtonDoubleClickEnabled"},
|
||||
{51, nullptr, "GetHomeButtonDoubleClickEnabled"},
|
||||
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
|
||||
{60, nullptr, "IsVrModeCurtainRequired"},
|
||||
{61, nullptr, "IsSleepRequiredByHighTemperature"},
|
||||
{62, nullptr, "IsSleepRequiredByLowBattery"},
|
||||
{70, &IAppletCommonFunctions::SetCpuBoostRequestPriority, "SetCpuBoostRequestPriority"},
|
||||
{80, nullptr, "SetHandlingCaptureButtonShortPressedMessageEnabledForApplet"},
|
||||
{81, nullptr, "SetHandlingCaptureButtonLongPressedMessageEnabledForApplet"},
|
||||
{90, nullptr, "OpenNamedChannelAsParent"},
|
||||
{91, nullptr, "OpenNamedChannelAsChild"},
|
||||
{100, nullptr, "SetApplicationCoreUsageMode"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IAppletCommonFunctions::~IAppletCommonFunctions() = default;
|
||||
|
||||
void IAppletCommonFunctions::SetCpuBoostRequestPriority(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
|
||||
@ -2049,8 +2202,8 @@ IProcessWindingController::IProcessWindingController(Core::System& system_)
|
||||
: ServiceFramework{system_, "IProcessWindingController"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetLaunchReason"},
|
||||
{11, nullptr, "OpenCallingLibraryApplet"},
|
||||
{0, &IProcessWindingController::GetLaunchReason, "GetLaunchReason"},
|
||||
{11, &IProcessWindingController::OpenCallingLibraryApplet, "OpenCallingLibraryApplet"},
|
||||
{21, nullptr, "PushContext"},
|
||||
{22, nullptr, "PopContext"},
|
||||
{23, nullptr, "CancelWindingReservation"},
|
||||
@ -2064,4 +2217,46 @@ IProcessWindingController::IProcessWindingController(Core::System& system_)
|
||||
}
|
||||
|
||||
IProcessWindingController::~IProcessWindingController() = default;
|
||||
|
||||
void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
struct AppletProcessLaunchReason {
|
||||
u8 flag;
|
||||
INSERT_PADDING_BYTES(3);
|
||||
};
|
||||
static_assert(sizeof(AppletProcessLaunchReason) == 0x4,
|
||||
"AppletProcessLaunchReason is an invalid size");
|
||||
|
||||
AppletProcessLaunchReason reason{
|
||||
.flag = 0,
|
||||
};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(reason);
|
||||
}
|
||||
|
||||
void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
|
||||
const auto applet_id = Applets::AppletId::MiiEdit;
|
||||
const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
|
||||
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
|
||||
applet_mode);
|
||||
|
||||
const auto& applet_manager{system.GetAppletManager()};
|
||||
const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
|
||||
|
||||
if (applet == nullptr) {
|
||||
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
|
||||
}
|
||||
} // namespace Service::AM
|
||||
|
@ -120,6 +120,9 @@ class IDisplayController final : public ServiceFramework<IDisplayController> {
|
||||
public:
|
||||
explicit IDisplayController(Core::System& system_);
|
||||
~IDisplayController() override;
|
||||
|
||||
private:
|
||||
void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
|
||||
@ -212,6 +215,11 @@ private:
|
||||
CaptureButtonLongPressing,
|
||||
};
|
||||
|
||||
enum class SysPlatformRegion : s32 {
|
||||
Global = 1,
|
||||
Terra = 2,
|
||||
};
|
||||
|
||||
void GetEventHandle(HLERequestContext& ctx);
|
||||
void ReceiveMessage(HLERequestContext& ctx);
|
||||
void GetCurrentFocusState(HLERequestContext& ctx);
|
||||
@ -227,6 +235,7 @@ private:
|
||||
void GetDefaultDisplayResolution(HLERequestContext& ctx);
|
||||
void SetCpuBoostMode(HLERequestContext& ctx);
|
||||
void PerformSystemButtonPressingIfInFocus(HLERequestContext& ctx);
|
||||
void GetSettingsPlatformRegion(HLERequestContext& ctx);
|
||||
void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(HLERequestContext& ctx);
|
||||
|
||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
||||
@ -294,6 +303,26 @@ class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletS
|
||||
public:
|
||||
explicit ILibraryAppletSelfAccessor(Core::System& system_);
|
||||
~ILibraryAppletSelfAccessor() override;
|
||||
|
||||
private:
|
||||
void PopInData(HLERequestContext& ctx);
|
||||
void PushOutData(HLERequestContext& ctx);
|
||||
void GetLibraryAppletInfo(HLERequestContext& ctx);
|
||||
void ExitProcessAndReturn(HLERequestContext& ctx);
|
||||
void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
|
||||
|
||||
void PushInShowMiiEditData();
|
||||
|
||||
std::deque<std::vector<u8>> queue_data;
|
||||
};
|
||||
|
||||
class IAppletCommonFunctions final : public ServiceFramework<IAppletCommonFunctions> {
|
||||
public:
|
||||
explicit IAppletCommonFunctions(Core::System& system_);
|
||||
~IAppletCommonFunctions() override;
|
||||
|
||||
private:
|
||||
void SetCpuBoostRequestPriority(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||
@ -378,6 +407,10 @@ class IProcessWindingController final : public ServiceFramework<IProcessWindingC
|
||||
public:
|
||||
explicit IProcessWindingController(Core::System& system_);
|
||||
~IProcessWindingController() override;
|
||||
|
||||
private:
|
||||
void GetLaunchReason(HLERequestContext& ctx);
|
||||
void OpenCallingLibraryApplet(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
||||
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
||||
{20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
|
||||
{21, nullptr, "GetAppletCommonFunctions"},
|
||||
{21, &ILibraryAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
|
||||
{22, nullptr, "GetHomeMenuFunctions"},
|
||||
{23, nullptr, "GetGlobalStateController"},
|
||||
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
||||
@ -86,14 +86,6 @@ private:
|
||||
rb.PushIpcInterface<IProcessWindingController>(system);
|
||||
}
|
||||
|
||||
void GetDebugFunctions(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IDebugFunctions>(system);
|
||||
}
|
||||
|
||||
void GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
@ -110,6 +102,22 @@ private:
|
||||
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
|
||||
}
|
||||
|
||||
void GetAppletCommonFunctions(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IAppletCommonFunctions>(system);
|
||||
}
|
||||
|
||||
void GetDebugFunctions(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IDebugFunctions>(system);
|
||||
}
|
||||
|
||||
Nvnflinger::Nvnflinger& nvnflinger;
|
||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
||||
};
|
||||
@ -133,7 +141,7 @@ public:
|
||||
{20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
|
||||
{21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
|
||||
{22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
|
||||
{23, nullptr, "GetAppletCommonFunctions"},
|
||||
{23, &ISystemAppletProxy::GetAppletCommonFunctions, "GetAppletCommonFunctions"},
|
||||
{1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
||||
};
|
||||
// clang-format on
|
||||
@ -182,14 +190,6 @@ private:
|
||||
rb.PushIpcInterface<IDisplayController>(system);
|
||||
}
|
||||
|
||||
void GetDebugFunctions(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IDebugFunctions>(system);
|
||||
}
|
||||
|
||||
void GetLibraryAppletCreator(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
@ -222,6 +222,22 @@ private:
|
||||
rb.PushIpcInterface<IApplicationCreator>(system);
|
||||
}
|
||||
|
||||
void GetAppletCommonFunctions(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IAppletCommonFunctions>(system);
|
||||
}
|
||||
|
||||
void GetDebugFunctions(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IDebugFunctions>(system);
|
||||
}
|
||||
|
||||
Nvnflinger::Nvnflinger& nvnflinger;
|
||||
std::shared_ptr<AppletMessageQueue> msg_queue;
|
||||
};
|
||||
|
@ -7,7 +7,9 @@
|
||||
#include "core/frontend/applets/mii_edit.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
#include "core/hle/service/am/applets/applet_mii_edit.h"
|
||||
#include "core/hle/service/mii/mii.h"
|
||||
#include "core/hle/service/mii/mii_manager.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
@ -56,6 +58,12 @@ void MiiEdit::Initialize() {
|
||||
sizeof(MiiEditAppletInputV4));
|
||||
break;
|
||||
}
|
||||
|
||||
manager = system.ServiceManager().GetService<Mii::MiiDBModule>("mii:e")->GetMiiManager();
|
||||
if (manager == nullptr) {
|
||||
manager = std::make_shared<Mii::MiiManager>();
|
||||
}
|
||||
manager->Initialize(metadata);
|
||||
}
|
||||
|
||||
bool MiiEdit::TransactionComplete() const {
|
||||
@ -78,22 +86,46 @@ void MiiEdit::Execute() {
|
||||
// This is a default stub for each of the MiiEdit applet modes.
|
||||
switch (applet_input_common.applet_mode) {
|
||||
case MiiEditAppletMode::ShowMiiEdit:
|
||||
case MiiEditAppletMode::AppendMii:
|
||||
case MiiEditAppletMode::AppendMiiImage:
|
||||
case MiiEditAppletMode::UpdateMiiImage:
|
||||
MiiEditOutput(MiiEditResult::Success, 0);
|
||||
break;
|
||||
case MiiEditAppletMode::CreateMii:
|
||||
case MiiEditAppletMode::EditMii: {
|
||||
Mii::CharInfo char_info{};
|
||||
case MiiEditAppletMode::AppendMii: {
|
||||
Mii::StoreData store_data{};
|
||||
store_data.BuildBase(Mii::Gender::Male);
|
||||
char_info.SetFromStoreData(store_data);
|
||||
store_data.BuildRandom(Mii::Age::All, Mii::Gender::All, Mii::Race::All);
|
||||
store_data.SetNickname({u'y', u'u', u'z', u'u'});
|
||||
store_data.SetChecksum();
|
||||
const auto result = manager->AddOrReplace(metadata, store_data);
|
||||
|
||||
if (result.IsError()) {
|
||||
MiiEditOutput(MiiEditResult::Cancel, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
s32 index = manager->FindIndex(store_data.GetCreateId(), false);
|
||||
|
||||
if (index == -1) {
|
||||
MiiEditOutput(MiiEditResult::Cancel, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
MiiEditOutput(MiiEditResult::Success, index);
|
||||
break;
|
||||
}
|
||||
case MiiEditAppletMode::CreateMii: {
|
||||
Mii::CharInfo char_info{};
|
||||
manager->BuildRandom(char_info, Mii::Age::All, Mii::Gender::All, Mii::Race::All);
|
||||
|
||||
const MiiEditCharInfo edit_char_info{
|
||||
.mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
|
||||
? applet_input_v4.char_info.mii_info
|
||||
: char_info},
|
||||
.mii_info{char_info},
|
||||
};
|
||||
|
||||
MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info);
|
||||
break;
|
||||
}
|
||||
case MiiEditAppletMode::EditMii: {
|
||||
const MiiEditCharInfo edit_char_info{
|
||||
.mii_info{applet_input_v4.char_info.mii_info},
|
||||
};
|
||||
|
||||
MiiEditOutputForCharInfoEditing(MiiEditResult::Success, edit_char_info);
|
||||
|
@ -11,6 +11,11 @@ namespace Core {
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
namespace Service::Mii {
|
||||
struct DatabaseSessionMetadata;
|
||||
class MiiManager;
|
||||
} // namespace Service::Mii
|
||||
|
||||
namespace Service::AM::Applets {
|
||||
|
||||
class MiiEdit final : public Applet {
|
||||
@ -40,6 +45,8 @@ private:
|
||||
MiiEditAppletInputV4 applet_input_v4{};
|
||||
|
||||
bool is_complete{false};
|
||||
std::shared_ptr<Mii::MiiManager> manager = nullptr;
|
||||
Mii::DatabaseSessionMetadata metadata{};
|
||||
};
|
||||
|
||||
} // namespace Service::AM::Applets
|
||||
|
@ -698,7 +698,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
|
||||
{19, nullptr, "FormatSdCardFileSystem"},
|
||||
{21, nullptr, "DeleteSaveDataFileSystem"},
|
||||
{22, &FSP_SRV::CreateSaveDataFileSystem, "CreateSaveDataFileSystem"},
|
||||
{23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"},
|
||||
{23, &FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId, "CreateSaveDataFileSystemBySystemSaveDataId"},
|
||||
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
|
||||
{25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
|
||||
{26, nullptr, "FormatSdCardDryRun"},
|
||||
@ -712,7 +712,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
|
||||
{35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
|
||||
{36, nullptr, "OpenHostFileSystemWithOption"},
|
||||
{51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"},
|
||||
{52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"},
|
||||
{52, &FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId, "OpenSaveDataFileSystemBySystemSaveDataId"},
|
||||
{53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"},
|
||||
{57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"},
|
||||
{58, nullptr, "ReadSaveDataFileSystemExtraData"},
|
||||
@ -870,6 +870,21 @@ void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) {
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
auto save_struct = rp.PopRaw<FileSys::SaveDataAttribute>();
|
||||
[[maybe_unused]] auto save_create_struct = rp.PopRaw<std::array<u8, 0x40>>();
|
||||
|
||||
LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo());
|
||||
|
||||
FileSys::VirtualDir save_data_dir{};
|
||||
fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandSystem, save_struct);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
@ -916,6 +931,11 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
|
||||
rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
|
||||
}
|
||||
|
||||
void FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
|
||||
OpenSaveDataFileSystem(ctx);
|
||||
}
|
||||
|
||||
void FSP_SRV::OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
|
||||
OpenSaveDataFileSystem(ctx);
|
||||
|
@ -39,7 +39,9 @@ private:
|
||||
void OpenFileSystemWithPatch(HLERequestContext& ctx);
|
||||
void OpenSdCardFileSystem(HLERequestContext& ctx);
|
||||
void CreateSaveDataFileSystem(HLERequestContext& ctx);
|
||||
void CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx);
|
||||
void OpenSaveDataFileSystem(HLERequestContext& ctx);
|
||||
void OpenSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx);
|
||||
void OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx);
|
||||
void OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx);
|
||||
void OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx);
|
||||
|
@ -346,6 +346,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
|
||||
}
|
||||
SignalStyleSetChangedEvent(npad_id);
|
||||
WriteEmptyEntry(controller.shared_memory);
|
||||
hid_core.SetLastActiveController(npad_id);
|
||||
}
|
||||
|
||||
void Controller_NPad::OnInit() {
|
||||
|
@ -18,8 +18,10 @@ namespace Service::Mii {
|
||||
|
||||
class IDatabaseService final : public ServiceFramework<IDatabaseService> {
|
||||
public:
|
||||
explicit IDatabaseService(Core::System& system_, bool is_system_)
|
||||
: ServiceFramework{system_, "IDatabaseService"}, is_system{is_system_} {
|
||||
explicit IDatabaseService(Core::System& system_, std::shared_ptr<MiiManager> mii_manager,
|
||||
bool is_system_)
|
||||
: ServiceFramework{system_, "IDatabaseService"}, manager{mii_manager}, is_system{
|
||||
is_system_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IDatabaseService::IsUpdated, "IsUpdated"},
|
||||
@ -54,7 +56,7 @@ public:
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
manager.Initialize(metadata);
|
||||
manager->Initialize(metadata);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -64,7 +66,7 @@ private:
|
||||
|
||||
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
|
||||
|
||||
const bool is_updated = manager.IsUpdated(metadata, source_flag);
|
||||
const bool is_updated = manager->IsUpdated(metadata, source_flag);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -74,7 +76,7 @@ private:
|
||||
void IsFullDatabase(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Mii, "called");
|
||||
|
||||
const bool is_full_database = manager.IsFullDatabase();
|
||||
const bool is_full_database = manager->IsFullDatabase();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -85,7 +87,7 @@ private:
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto source_flag{rp.PopRaw<SourceFlag>()};
|
||||
|
||||
const u32 mii_count = manager.GetCount(metadata, source_flag);
|
||||
const u32 mii_count = manager->GetCount(metadata, source_flag);
|
||||
|
||||
LOG_DEBUG(Service_Mii, "called with source_flag={}, mii_count={}", source_flag, mii_count);
|
||||
|
||||
@ -101,7 +103,7 @@ private:
|
||||
|
||||
u32 mii_count{};
|
||||
std::vector<CharInfoElement> char_info_elements(output_size);
|
||||
const auto result = manager.Get(metadata, char_info_elements, mii_count, source_flag);
|
||||
const auto result = manager->Get(metadata, char_info_elements, mii_count, source_flag);
|
||||
|
||||
if (mii_count != 0) {
|
||||
ctx.WriteBuffer(char_info_elements);
|
||||
@ -122,7 +124,7 @@ private:
|
||||
|
||||
u32 mii_count{};
|
||||
std::vector<CharInfo> char_info(output_size);
|
||||
const auto result = manager.Get(metadata, char_info, mii_count, source_flag);
|
||||
const auto result = manager->Get(metadata, char_info, mii_count, source_flag);
|
||||
|
||||
if (mii_count != 0) {
|
||||
ctx.WriteBuffer(char_info);
|
||||
@ -144,7 +146,7 @@ private:
|
||||
LOG_INFO(Service_Mii, "called with source_flag={}", source_flag);
|
||||
|
||||
CharInfo new_char_info{};
|
||||
const auto result = manager.UpdateLatest(metadata, new_char_info, char_info, source_flag);
|
||||
const auto result = manager->UpdateLatest(metadata, new_char_info, char_info, source_flag);
|
||||
if (result.IsFailure()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
@ -183,7 +185,7 @@ private:
|
||||
}
|
||||
|
||||
CharInfo char_info{};
|
||||
manager.BuildRandom(char_info, age, gender, race);
|
||||
manager->BuildRandom(char_info, age, gender, race);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -203,7 +205,7 @@ private:
|
||||
}
|
||||
|
||||
CharInfo char_info{};
|
||||
manager.BuildDefault(char_info, index);
|
||||
manager->BuildDefault(char_info, index);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -217,7 +219,7 @@ private:
|
||||
|
||||
u32 mii_count{};
|
||||
std::vector<StoreDataElement> store_data_elements(output_size);
|
||||
const auto result = manager.Get(metadata, store_data_elements, mii_count, source_flag);
|
||||
const auto result = manager->Get(metadata, store_data_elements, mii_count, source_flag);
|
||||
|
||||
if (mii_count != 0) {
|
||||
ctx.WriteBuffer(store_data_elements);
|
||||
@ -238,7 +240,7 @@ private:
|
||||
|
||||
u32 mii_count{};
|
||||
std::vector<StoreData> store_data(output_size);
|
||||
const auto result = manager.Get(metadata, store_data, mii_count, source_flag);
|
||||
const auto result = manager->Get(metadata, store_data, mii_count, source_flag);
|
||||
|
||||
if (mii_count != 0) {
|
||||
ctx.WriteBuffer(store_data);
|
||||
@ -266,7 +268,7 @@ private:
|
||||
|
||||
StoreData new_store_data{};
|
||||
if (result.IsSuccess()) {
|
||||
result = manager.UpdateLatest(metadata, new_store_data, store_data, source_flag);
|
||||
result = manager->UpdateLatest(metadata, new_store_data, store_data, source_flag);
|
||||
}
|
||||
|
||||
if (result.IsFailure()) {
|
||||
@ -288,7 +290,7 @@ private:
|
||||
LOG_INFO(Service_Mii, "called with create_id={}, is_special={}",
|
||||
create_id.FormattedString(), is_special);
|
||||
|
||||
const s32 index = manager.FindIndex(create_id, is_special);
|
||||
const s32 index = manager->FindIndex(create_id, is_special);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -309,14 +311,14 @@ private:
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
const u32 count = manager.GetCount(metadata, SourceFlag::Database);
|
||||
const u32 count = manager->GetCount(metadata, SourceFlag::Database);
|
||||
if (new_index < 0 || new_index >= static_cast<s32>(count)) {
|
||||
result = ResultInvalidArgument;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager.Move(metadata, new_index, create_id);
|
||||
result = manager->Move(metadata, new_index, create_id);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -336,7 +338,7 @@ private:
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager.AddOrReplace(metadata, store_data);
|
||||
result = manager->AddOrReplace(metadata, store_data);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -356,7 +358,7 @@ private:
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager.Delete(metadata, create_id);
|
||||
result = manager->Delete(metadata, create_id);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -376,7 +378,7 @@ private:
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager.DestroyFile(metadata);
|
||||
result = manager->DestroyFile(metadata);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -396,7 +398,7 @@ private:
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager.DeleteFile();
|
||||
result = manager->DeleteFile();
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -416,7 +418,7 @@ private:
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
result = manager.Format(metadata);
|
||||
result = manager->Format(metadata);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
@ -434,7 +436,7 @@ private:
|
||||
}
|
||||
|
||||
if (result.IsSuccess()) {
|
||||
is_broken_with_clear_flag = manager.IsBrokenWithClearFlag(metadata);
|
||||
is_broken_with_clear_flag = manager->IsBrokenWithClearFlag(metadata);
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
@ -449,7 +451,7 @@ private:
|
||||
LOG_DEBUG(Service_Mii, "called");
|
||||
|
||||
s32 index{};
|
||||
const auto result = manager.GetIndex(metadata, info, index);
|
||||
const auto result = manager->GetIndex(metadata, info, index);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(result);
|
||||
@ -462,7 +464,7 @@ private:
|
||||
|
||||
LOG_INFO(Service_Mii, "called, interface_version={:08X}", interface_version);
|
||||
|
||||
manager.SetInterfaceVersion(metadata, interface_version);
|
||||
manager->SetInterfaceVersion(metadata, interface_version);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
@ -475,7 +477,7 @@ private:
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
CharInfo char_info{};
|
||||
const auto result = manager.ConvertV3ToCharInfo(char_info, mii_v3);
|
||||
const auto result = manager->ConvertV3ToCharInfo(char_info, mii_v3);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||
rb.Push(result);
|
||||
@ -489,7 +491,7 @@ private:
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
CharInfo char_info{};
|
||||
const auto result = manager.ConvertCoreDataToCharInfo(char_info, core_data);
|
||||
const auto result = manager->ConvertCoreDataToCharInfo(char_info, core_data);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
|
||||
rb.Push(result);
|
||||
@ -503,7 +505,7 @@ private:
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
CoreData core_data{};
|
||||
const auto result = manager.ConvertCharInfoToCoreData(core_data, char_info);
|
||||
const auto result = manager->ConvertCharInfoToCoreData(core_data, char_info);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CoreData) / sizeof(u32)};
|
||||
rb.Push(result);
|
||||
@ -516,41 +518,46 @@ private:
|
||||
|
||||
LOG_INFO(Service_Mii, "called");
|
||||
|
||||
const auto result = manager.Append(metadata, char_info);
|
||||
const auto result = manager->Append(metadata, char_info);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
}
|
||||
|
||||
MiiManager manager{};
|
||||
std::shared_ptr<MiiManager> manager = nullptr;
|
||||
DatabaseSessionMetadata metadata{};
|
||||
bool is_system{};
|
||||
};
|
||||
|
||||
class MiiDBModule final : public ServiceFramework<MiiDBModule> {
|
||||
public:
|
||||
explicit MiiDBModule(Core::System& system_, const char* name_, bool is_system_)
|
||||
: ServiceFramework{system_, name_}, is_system{is_system_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
|
||||
};
|
||||
// clang-format on
|
||||
MiiDBModule::MiiDBModule(Core::System& system_, const char* name_,
|
||||
std::shared_ptr<MiiManager> mii_manager, bool is_system_)
|
||||
: ServiceFramework{system_, name_}, manager{mii_manager}, is_system{is_system_} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
RegisterHandlers(functions);
|
||||
|
||||
if (manager == nullptr) {
|
||||
manager = std::make_shared<MiiManager>();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void GetDatabaseService(HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IDatabaseService>(system, is_system);
|
||||
MiiDBModule::~MiiDBModule() = default;
|
||||
|
||||
LOG_DEBUG(Service_Mii, "called");
|
||||
}
|
||||
void MiiDBModule::GetDatabaseService(HLERequestContext& ctx) {
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IDatabaseService>(system, manager, is_system);
|
||||
|
||||
bool is_system{};
|
||||
};
|
||||
LOG_DEBUG(Service_Mii, "called");
|
||||
}
|
||||
|
||||
std::shared_ptr<MiiManager> MiiDBModule::GetMiiManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
class MiiImg final : public ServiceFramework<MiiImg> {
|
||||
public:
|
||||
@ -596,11 +603,12 @@ private:
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
std::shared_ptr<MiiManager> manager = nullptr;
|
||||
|
||||
server_manager->RegisterNamedService("mii:e",
|
||||
std::make_shared<MiiDBModule>(system, "mii:e", true));
|
||||
server_manager->RegisterNamedService("mii:u",
|
||||
std::make_shared<MiiDBModule>(system, "mii:u", false));
|
||||
server_manager->RegisterNamedService(
|
||||
"mii:e", std::make_shared<MiiDBModule>(system, "mii:e", manager, true));
|
||||
server_manager->RegisterNamedService(
|
||||
"mii:u", std::make_shared<MiiDBModule>(system, "mii:u", manager, false));
|
||||
server_manager->RegisterNamedService("miiimg", std::make_shared<MiiImg>(system));
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
@ -3,11 +3,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Mii {
|
||||
class MiiManager;
|
||||
|
||||
class MiiDBModule final : public ServiceFramework<MiiDBModule> {
|
||||
public:
|
||||
explicit MiiDBModule(Core::System& system_, const char* name_,
|
||||
std::shared_ptr<MiiManager> mii_manager, bool is_system_);
|
||||
~MiiDBModule() override;
|
||||
|
||||
std::shared_ptr<MiiManager> GetMiiManager();
|
||||
|
||||
private:
|
||||
void GetDatabaseService(HLERequestContext& ctx);
|
||||
|
||||
std::shared_ptr<MiiManager> manager = nullptr;
|
||||
bool is_system{};
|
||||
};
|
||||
|
||||
void LoopProcess(Core::System& system);
|
||||
|
||||
|
@ -130,11 +130,11 @@ Result MiiManager::GetIndex(const DatabaseSessionMetadata& metadata, const CharI
|
||||
}
|
||||
|
||||
s32 index{};
|
||||
Result result = {};
|
||||
// FindIndex(index);
|
||||
const bool is_special = metadata.magic == MiiMagic;
|
||||
const auto result = database_manager.FindIndex(index, char_info.GetCreateId(), is_special);
|
||||
|
||||
if (result.IsError()) {
|
||||
return ResultNotFound;
|
||||
index = -1;
|
||||
}
|
||||
|
||||
if (index == -1) {
|
||||
|
@ -614,7 +614,7 @@ struct Nickname {
|
||||
}
|
||||
|
||||
std::size_t index = 1;
|
||||
while (data[index] != 0) {
|
||||
while (index < MaxNameSize && data[index] != 0) {
|
||||
index++;
|
||||
}
|
||||
while (index < MaxNameSize && data[index] == 0) {
|
||||
|
@ -37,7 +37,7 @@ void CharInfo::SetFromStoreData(const StoreData& store_data) {
|
||||
eyebrow_aspect = store_data.GetEyebrowAspect();
|
||||
eyebrow_rotate = store_data.GetEyebrowRotate();
|
||||
eyebrow_x = store_data.GetEyebrowX();
|
||||
eyebrow_y = store_data.GetEyebrowY() + 3;
|
||||
eyebrow_y = store_data.GetEyebrowY();
|
||||
nose_type = store_data.GetNoseType();
|
||||
nose_scale = store_data.GetNoseScale();
|
||||
nose_y = store_data.GetNoseY();
|
||||
|
@ -171,7 +171,7 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) {
|
||||
u8 glasses_type{};
|
||||
while (glasses_type_start < glasses_type_info.values[glasses_type]) {
|
||||
if (++glasses_type >= glasses_type_info.values_count) {
|
||||
ASSERT(false);
|
||||
glasses_type = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -179,6 +179,7 @@ void CoreData::BuildRandom(Age age, Gender gender, Race race) {
|
||||
SetGlassType(static_cast<GlassType>(glasses_type));
|
||||
SetGlassColor(RawData::GetGlassColorFromVer3(0));
|
||||
SetGlassScale(4);
|
||||
SetGlassY(static_cast<u8>(axis_y + 10));
|
||||
|
||||
SetMoleType(MoleType::None);
|
||||
SetMoleScale(4);
|
||||
|
@ -1716,18 +1716,18 @@ const std::array<RandomMiiData4, 18> RandomMiiMouthType{
|
||||
const std::array<RandomMiiData2, 3> RandomMiiGlassType{
|
||||
RandomMiiData2{
|
||||
.arg_1 = 0,
|
||||
.values_count = 9,
|
||||
.values = {90, 94, 96, 100, 0, 0, 0, 0, 0},
|
||||
.values_count = 4,
|
||||
.values = {90, 94, 96, 100},
|
||||
},
|
||||
RandomMiiData2{
|
||||
.arg_1 = 1,
|
||||
.values_count = 9,
|
||||
.values = {83, 86, 90, 93, 94, 96, 98, 100, 0},
|
||||
.values_count = 8,
|
||||
.values = {83, 86, 90, 93, 94, 96, 98, 100},
|
||||
},
|
||||
RandomMiiData2{
|
||||
.arg_1 = 2,
|
||||
.values_count = 9,
|
||||
.values = {78, 83, 0, 93, 0, 0, 98, 100, 0},
|
||||
.values_count = 8,
|
||||
.values = {78, 83, 0, 93, 0, 0, 98, 100},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -144,7 +144,7 @@ IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const ch
|
||||
{3, &IPlatformServiceManager::GetSharedMemoryAddressOffset, "GetSharedMemoryAddressOffset"},
|
||||
{4, &IPlatformServiceManager::GetSharedMemoryNativeHandle, "GetSharedMemoryNativeHandle"},
|
||||
{5, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriority"},
|
||||
{6, nullptr, "GetSharedFontInOrderOfPriorityForSystem"},
|
||||
{6, &IPlatformServiceManager::GetSharedFontInOrderOfPriority, "GetSharedFontInOrderOfPriorityForSystem"},
|
||||
{100, nullptr, "RequestApplicationFunctionAuthorization"},
|
||||
{101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
|
||||
{102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
|
||||
@ -262,8 +262,17 @@ void IPlatformServiceManager::GetSharedMemoryNativeHandle(HLERequestContext& ctx
|
||||
}
|
||||
|
||||
void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext& ctx) {
|
||||
// The maximum number of elements that can be returned is 6. Regardless of the available fonts
|
||||
// or buffer size.
|
||||
constexpr std::size_t MaxElementCount = 6;
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u64 language_code{rp.Pop<u64>()}; // TODO(ogniK): Find out what this is used for
|
||||
const std::size_t font_codes_count =
|
||||
std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(0));
|
||||
const std::size_t font_offsets_count =
|
||||
std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(1));
|
||||
const std::size_t font_sizes_count =
|
||||
std::min(MaxElementCount, ctx.GetWriteBufferNumElements<u32>(2));
|
||||
LOG_DEBUG(Service_NS, "called, language_code={:X}", language_code);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
@ -280,9 +289,9 @@ void IPlatformServiceManager::GetSharedFontInOrderOfPriority(HLERequestContext&
|
||||
}
|
||||
|
||||
// Resize buffers if game requests smaller size output
|
||||
font_codes.resize(std::min(font_codes.size(), ctx.GetWriteBufferNumElements<u32>(0)));
|
||||
font_offsets.resize(std::min(font_offsets.size(), ctx.GetWriteBufferNumElements<u32>(1)));
|
||||
font_sizes.resize(std::min(font_sizes.size(), ctx.GetWriteBufferNumElements<u32>(2)));
|
||||
font_codes.resize(std::min(font_codes.size(), font_codes_count));
|
||||
font_offsets.resize(std::min(font_offsets.size(), font_offsets_count));
|
||||
font_sizes.resize(std::min(font_sizes.size(), font_sizes_count));
|
||||
|
||||
ctx.WriteBuffer(font_codes, 0);
|
||||
ctx.WriteBuffer(font_offsets, 1);
|
||||
|
@ -7,15 +7,12 @@
|
||||
|
||||
namespace Shader::Backend::SPIRV {
|
||||
namespace {
|
||||
Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
|
||||
if (!index.IsImmediate()) {
|
||||
throw NotImplementedException("Indirect image indexing");
|
||||
}
|
||||
Id Image(EmitContext& ctx, IR::TextureInstInfo info) {
|
||||
if (info.type == TextureType::Buffer) {
|
||||
const ImageBufferDefinition def{ctx.image_buffers.at(index.U32())};
|
||||
const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)};
|
||||
return def.id;
|
||||
} else {
|
||||
const ImageDefinition def{ctx.images.at(index.U32())};
|
||||
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
|
||||
return def.id;
|
||||
}
|
||||
}
|
||||
@ -28,8 +25,12 @@ std::pair<Id, Id> AtomicArgs(EmitContext& ctx) {
|
||||
|
||||
Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id value,
|
||||
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
|
||||
if (!index.IsImmediate() || index.U32() != 0) {
|
||||
// TODO: handle layers
|
||||
throw NotImplementedException("Image indexing");
|
||||
}
|
||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||
const Id image{Image(ctx, index, info)};
|
||||
const Id image{Image(ctx, info)};
|
||||
const Id pointer{ctx.OpImageTexelPointer(ctx.image_u32, image, coords, ctx.Const(0U))};
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value);
|
||||
|
@ -74,11 +74,6 @@ spv::ImageFormat GetImageFormat(ImageFormat format) {
|
||||
throw InvalidArgument("Invalid image format {}", format);
|
||||
}
|
||||
|
||||
spv::ImageFormat GetImageFormatForBuffer(ImageFormat format) {
|
||||
const auto spv_format = GetImageFormat(format);
|
||||
return spv_format == spv::ImageFormat::Unknown ? spv::ImageFormat::R32ui : spv_format;
|
||||
}
|
||||
|
||||
Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
|
||||
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
||||
const Id type{ctx.U32[1]};
|
||||
@ -1275,7 +1270,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
|
||||
if (desc.count != 1) {
|
||||
throw NotImplementedException("Array of image buffers");
|
||||
}
|
||||
const spv::ImageFormat format{GetImageFormatForBuffer(desc.format)};
|
||||
const spv::ImageFormat format{GetImageFormat(desc.format)};
|
||||
const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)};
|
||||
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
|
||||
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
|
||||
|
@ -109,10 +109,11 @@ void MaxwellDMA::Launch() {
|
||||
const bool is_const_a_dst = regs.remap_const.dst_x == RemapConst::Swizzle::CONST_A;
|
||||
if (regs.launch_dma.remap_enable != 0 && is_const_a_dst) {
|
||||
ASSERT(regs.remap_const.component_size_minus_one == 3);
|
||||
accelerate.BufferClear(regs.offset_out, regs.line_length_in, regs.remap_consta_value);
|
||||
accelerate.BufferClear(regs.offset_out, regs.line_length_in,
|
||||
regs.remap_const.remap_consta_value);
|
||||
read_buffer.resize_destructive(regs.line_length_in * sizeof(u32));
|
||||
std::span<u32> span(reinterpret_cast<u32*>(read_buffer.data()), regs.line_length_in);
|
||||
std::ranges::fill(span, regs.remap_consta_value);
|
||||
std::ranges::fill(span, regs.remap_const.remap_consta_value);
|
||||
memory_manager.WriteBlockUnsafe(regs.offset_out,
|
||||
reinterpret_cast<u8*>(read_buffer.data()),
|
||||
regs.line_length_in * sizeof(u32));
|
||||
|
@ -214,14 +214,15 @@ public:
|
||||
NO_WRITE = 6,
|
||||
};
|
||||
|
||||
PackedGPUVAddr address;
|
||||
u32 remap_consta_value;
|
||||
u32 remap_constb_value;
|
||||
|
||||
union {
|
||||
BitField<0, 12, u32> dst_components_raw;
|
||||
BitField<0, 3, Swizzle> dst_x;
|
||||
BitField<4, 3, Swizzle> dst_y;
|
||||
BitField<8, 3, Swizzle> dst_z;
|
||||
BitField<12, 3, Swizzle> dst_w;
|
||||
BitField<0, 12, u32> dst_components_raw;
|
||||
BitField<16, 2, u32> component_size_minus_one;
|
||||
BitField<20, 2, u32> num_src_components_minus_one;
|
||||
BitField<24, 2, u32> num_dst_components_minus_one;
|
||||
@ -274,55 +275,57 @@ private:
|
||||
struct Regs {
|
||||
union {
|
||||
struct {
|
||||
u32 reserved[0x40];
|
||||
INSERT_PADDING_BYTES_NOINIT(0x100);
|
||||
u32 nop;
|
||||
u32 reserved01[0xf];
|
||||
INSERT_PADDING_BYTES_NOINIT(0x3C);
|
||||
u32 pm_trigger;
|
||||
u32 reserved02[0x3f];
|
||||
INSERT_PADDING_BYTES_NOINIT(0xFC);
|
||||
Semaphore semaphore;
|
||||
u32 reserved03[0x2];
|
||||
INSERT_PADDING_BYTES_NOINIT(0x8);
|
||||
RenderEnable render_enable;
|
||||
PhysMode src_phys_mode;
|
||||
PhysMode dst_phys_mode;
|
||||
u32 reserved04[0x26];
|
||||
INSERT_PADDING_BYTES_NOINIT(0x98);
|
||||
LaunchDMA launch_dma;
|
||||
u32 reserved05[0x3f];
|
||||
INSERT_PADDING_BYTES_NOINIT(0xFC);
|
||||
PackedGPUVAddr offset_in;
|
||||
PackedGPUVAddr offset_out;
|
||||
s32 pitch_in;
|
||||
s32 pitch_out;
|
||||
u32 line_length_in;
|
||||
u32 line_count;
|
||||
u32 reserved06[0xb6];
|
||||
u32 remap_consta_value;
|
||||
u32 remap_constb_value;
|
||||
INSERT_PADDING_BYTES_NOINIT(0x2E0);
|
||||
RemapConst remap_const;
|
||||
DMA::Parameters dst_params;
|
||||
u32 reserved07[0x1];
|
||||
INSERT_PADDING_BYTES_NOINIT(0x4);
|
||||
DMA::Parameters src_params;
|
||||
u32 reserved08[0x275];
|
||||
INSERT_PADDING_BYTES_NOINIT(0x9D4);
|
||||
u32 pm_trigger_end;
|
||||
u32 reserved09[0x3ba];
|
||||
INSERT_PADDING_BYTES_NOINIT(0xEE8);
|
||||
};
|
||||
std::array<u32, NUM_REGS> reg_array;
|
||||
};
|
||||
} regs{};
|
||||
static_assert(sizeof(Regs) == NUM_REGS * 4);
|
||||
|
||||
#define ASSERT_REG_POSITION(field_name, position) \
|
||||
static_assert(offsetof(MaxwellDMA::Regs, field_name) == position * 4, \
|
||||
static_assert(offsetof(MaxwellDMA::Regs, field_name) == position, \
|
||||
"Field " #field_name " has invalid position")
|
||||
|
||||
ASSERT_REG_POSITION(launch_dma, 0xC0);
|
||||
ASSERT_REG_POSITION(offset_in, 0x100);
|
||||
ASSERT_REG_POSITION(offset_out, 0x102);
|
||||
ASSERT_REG_POSITION(pitch_in, 0x104);
|
||||
ASSERT_REG_POSITION(pitch_out, 0x105);
|
||||
ASSERT_REG_POSITION(line_length_in, 0x106);
|
||||
ASSERT_REG_POSITION(line_count, 0x107);
|
||||
ASSERT_REG_POSITION(remap_const, 0x1C0);
|
||||
ASSERT_REG_POSITION(dst_params, 0x1C3);
|
||||
ASSERT_REG_POSITION(src_params, 0x1CA);
|
||||
|
||||
ASSERT_REG_POSITION(semaphore, 0x240);
|
||||
ASSERT_REG_POSITION(render_enable, 0x254);
|
||||
ASSERT_REG_POSITION(src_phys_mode, 0x260);
|
||||
ASSERT_REG_POSITION(launch_dma, 0x300);
|
||||
ASSERT_REG_POSITION(offset_in, 0x400);
|
||||
ASSERT_REG_POSITION(offset_out, 0x408);
|
||||
ASSERT_REG_POSITION(pitch_in, 0x410);
|
||||
ASSERT_REG_POSITION(pitch_out, 0x414);
|
||||
ASSERT_REG_POSITION(line_length_in, 0x418);
|
||||
ASSERT_REG_POSITION(line_count, 0x41C);
|
||||
ASSERT_REG_POSITION(remap_const, 0x700);
|
||||
ASSERT_REG_POSITION(dst_params, 0x70C);
|
||||
ASSERT_REG_POSITION(src_params, 0x728);
|
||||
ASSERT_REG_POSITION(pm_trigger_end, 0x1114);
|
||||
#undef ASSERT_REG_POSITION
|
||||
};
|
||||
|
||||
|
@ -185,7 +185,7 @@ struct FormatTuple {
|
||||
{VK_FORMAT_BC2_SRGB_BLOCK}, // BC2_SRGB
|
||||
{VK_FORMAT_BC3_SRGB_BLOCK}, // BC3_SRGB
|
||||
{VK_FORMAT_BC7_SRGB_BLOCK}, // BC7_SRGB
|
||||
{VK_FORMAT_R4G4B4A4_UNORM_PACK16}, // A4B4G4R4_UNORM
|
||||
{VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT}, // A4B4G4R4_UNORM
|
||||
{VK_FORMAT_R4G4_UNORM_PACK8}, // G4R4_UNORM
|
||||
{VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB
|
||||
{VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB
|
||||
|
@ -120,19 +120,9 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
return usage;
|
||||
}
|
||||
|
||||
/// Returns the preferred format for a VkImage
|
||||
[[nodiscard]] PixelFormat StorageFormat(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PixelFormat::A8B8G8R8_SRGB:
|
||||
return PixelFormat::A8B8G8R8_UNORM;
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] VkImageCreateInfo MakeImageCreateInfo(const Device& device, const ImageInfo& info) {
|
||||
const PixelFormat format = StorageFormat(info.format);
|
||||
const auto format_info = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, format);
|
||||
const auto format_info =
|
||||
MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, false, info.format);
|
||||
VkImageCreateFlags flags{};
|
||||
if (info.type == ImageType::e2D && info.resources.layers >= 6 &&
|
||||
info.size.width == info.size.height && !device.HasBrokenCubeImageCompability()) {
|
||||
@ -157,7 +147,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
|
||||
.arrayLayers = static_cast<u32>(info.resources.layers),
|
||||
.samples = ConvertSampleCount(info.num_samples),
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = ImageUsageFlags(format_info, format),
|
||||
.usage = ImageUsageFlags(format_info, info.format),
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
@ -600,7 +590,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
|
||||
}
|
||||
|
||||
void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4>& swizzle,
|
||||
bool emulate_bgr565) {
|
||||
bool emulate_bgr565, bool emulate_a4b4g4r4) {
|
||||
switch (format) {
|
||||
case PixelFormat::A1B5G5R5_UNORM:
|
||||
std::ranges::transform(swizzle, swizzle.begin(), SwapBlueRed);
|
||||
@ -616,6 +606,11 @@ void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4
|
||||
case PixelFormat::G4R4_UNORM:
|
||||
std::ranges::transform(swizzle, swizzle.begin(), SwapGreenRed);
|
||||
break;
|
||||
case PixelFormat::A4B4G4R4_UNORM:
|
||||
if (emulate_a4b4g4r4) {
|
||||
std::ranges::reverse(swizzle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1044,15 +1039,27 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
|
||||
dst_region, src_region, filter, operation);
|
||||
return;
|
||||
}
|
||||
ASSERT(src.format == dst.format);
|
||||
if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
if (!device.IsBlitDepthStencilSupported()) {
|
||||
const auto format = src.format;
|
||||
const auto can_blit_depth_stencil = [this, format] {
|
||||
switch (format) {
|
||||
case VideoCore::Surface::PixelFormat::D24_UNORM_S8_UINT:
|
||||
case VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM:
|
||||
return device.IsBlitDepth24Stencil8Supported();
|
||||
case VideoCore::Surface::PixelFormat::D32_FLOAT_S8_UINT:
|
||||
return device.IsBlitDepth32Stencil8Supported();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}();
|
||||
if (!can_blit_depth_stencil) {
|
||||
UNIMPLEMENTED_IF(is_src_msaa || is_dst_msaa);
|
||||
blit_image_helper.BlitDepthStencil(dst_framebuffer, src.DepthView(), src.StencilView(),
|
||||
dst_region, src_region, filter, operation);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ASSERT(src.format == dst.format);
|
||||
ASSERT(!(is_dst_msaa && !is_src_msaa));
|
||||
ASSERT(operation == Fermi2D::Operation::SrcCopy);
|
||||
|
||||
@ -1626,8 +1633,8 @@ bool Image::NeedsScaleHelper() const {
|
||||
return true;
|
||||
}
|
||||
static constexpr auto OPTIMAL_FORMAT = FormatType::Optimal;
|
||||
const PixelFormat format = StorageFormat(info.format);
|
||||
const auto vk_format = MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, format).format;
|
||||
const auto vk_format =
|
||||
MaxwellToVK::SurfaceFormat(device, OPTIMAL_FORMAT, false, info.format).format;
|
||||
const auto blit_usage = VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
|
||||
const bool needs_blit_helper = !device.IsFormatSupported(vk_format, blit_usage, OPTIMAL_FORMAT);
|
||||
return needs_blit_helper;
|
||||
@ -1649,7 +1656,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
|
||||
};
|
||||
if (!info.IsRenderTarget()) {
|
||||
swizzle = info.Swizzle();
|
||||
TryTransformSwizzleIfNeeded(format, swizzle, device->MustEmulateBGR565());
|
||||
TryTransformSwizzleIfNeeded(format, swizzle, device->MustEmulateBGR565(),
|
||||
!device->IsExt4444FormatsSupported());
|
||||
if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) {
|
||||
std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed);
|
||||
}
|
||||
|
@ -76,6 +76,11 @@ constexpr std::array VK_FORMAT_R32G32B32_SFLOAT{
|
||||
VK_FORMAT_UNDEFINED,
|
||||
};
|
||||
|
||||
constexpr std::array VK_FORMAT_A4B4G4R4_UNORM_PACK16{
|
||||
VK_FORMAT_R4G4B4A4_UNORM_PACK16,
|
||||
VK_FORMAT_UNDEFINED,
|
||||
};
|
||||
|
||||
} // namespace Alternatives
|
||||
|
||||
enum class NvidiaArchitecture {
|
||||
@ -110,6 +115,8 @@ constexpr const VkFormat* GetFormatAlternatives(VkFormat format) {
|
||||
return Alternatives::R8G8B8_SSCALED.data();
|
||||
case VK_FORMAT_R32G32B32_SFLOAT:
|
||||
return Alternatives::VK_FORMAT_R32G32B32_SFLOAT.data();
|
||||
case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT:
|
||||
return Alternatives::VK_FORMAT_A4B4G4R4_UNORM_PACK16.data();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
@ -238,6 +245,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica
|
||||
VK_FORMAT_R32_SINT,
|
||||
VK_FORMAT_R32_UINT,
|
||||
VK_FORMAT_R4G4B4A4_UNORM_PACK16,
|
||||
VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
|
||||
VK_FORMAT_R4G4_UNORM_PACK8,
|
||||
VK_FORMAT_R5G5B5A1_UNORM_PACK16,
|
||||
VK_FORMAT_R5G6B5_UNORM_PACK16,
|
||||
@ -420,7 +428,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||
first_next = &diagnostics_nv;
|
||||
}
|
||||
|
||||
is_blit_depth_stencil_supported = TestDepthStencilBlits();
|
||||
is_blit_depth24_stencil8_supported = TestDepthStencilBlits(VK_FORMAT_D24_UNORM_S8_UINT);
|
||||
is_blit_depth32_stencil8_supported = TestDepthStencilBlits(VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||
is_optimal_astc_supported = ComputeIsOptimalAstcSupported();
|
||||
is_warp_potentially_bigger = !extensions.subgroup_size_control ||
|
||||
properties.subgroup_size_control.maxSubgroupSize > GuestWarpSize;
|
||||
@ -774,14 +783,13 @@ bool Device::ComputeIsOptimalAstcSupported() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Device::TestDepthStencilBlits() const {
|
||||
bool Device::TestDepthStencilBlits(VkFormat format) const {
|
||||
static constexpr VkFormatFeatureFlags required_features =
|
||||
VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
|
||||
const auto test_features = [](VkFormatProperties props) {
|
||||
return (props.optimalTilingFeatures & required_features) == required_features;
|
||||
};
|
||||
return test_features(format_properties.at(VK_FORMAT_D32_SFLOAT_S8_UINT)) &&
|
||||
test_features(format_properties.at(VK_FORMAT_D24_UNORM_S8_UINT));
|
||||
return test_features(format_properties.at(format));
|
||||
}
|
||||
|
||||
bool Device::IsFormatSupported(VkFormat wanted_format, VkFormatFeatureFlags wanted_usage,
|
||||
|
@ -45,6 +45,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||
FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \
|
||||
FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \
|
||||
FEATURE(EXT, ExtendedDynamicState3, EXTENDED_DYNAMIC_STATE_3, extended_dynamic_state3) \
|
||||
FEATURE(EXT, 4444Formats, 4444_FORMATS, format_a4b4g4r4) \
|
||||
FEATURE(EXT, IndexTypeUint8, INDEX_TYPE_UINT8, index_type_uint8) \
|
||||
FEATURE(EXT, LineRasterization, LINE_RASTERIZATION, line_rasterization) \
|
||||
FEATURE(EXT, PrimitiveTopologyListRestart, PRIMITIVE_TOPOLOGY_LIST_RESTART, \
|
||||
@ -97,6 +98,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||
EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME) \
|
||||
EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME) \
|
||||
EXTENSION_NAME(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME) \
|
||||
EXTENSION_NAME(VK_EXT_4444_FORMATS_EXTENSION_NAME) \
|
||||
EXTENSION_NAME(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME) \
|
||||
EXTENSION_NAME(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME) \
|
||||
EXTENSION_NAME(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME) \
|
||||
@ -144,6 +146,7 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
||||
#define FOR_EACH_VK_RECOMMENDED_FEATURE(FEATURE_NAME) \
|
||||
FEATURE_NAME(custom_border_color, customBorderColors) \
|
||||
FEATURE_NAME(extended_dynamic_state, extendedDynamicState) \
|
||||
FEATURE_NAME(format_a4b4g4r4, formatA4B4G4R4) \
|
||||
FEATURE_NAME(index_type_uint8, indexTypeUint8) \
|
||||
FEATURE_NAME(primitive_topology_list_restart, primitiveTopologyListRestart) \
|
||||
FEATURE_NAME(provoking_vertex, provokingVertexLast) \
|
||||
@ -359,9 +362,14 @@ public:
|
||||
return features.features.depthBounds;
|
||||
}
|
||||
|
||||
/// Returns true when blitting from and to depth stencil images is supported.
|
||||
bool IsBlitDepthStencilSupported() const {
|
||||
return is_blit_depth_stencil_supported;
|
||||
/// Returns true when blitting from and to D24S8 images is supported.
|
||||
bool IsBlitDepth24Stencil8Supported() const {
|
||||
return is_blit_depth24_stencil8_supported;
|
||||
}
|
||||
|
||||
/// Returns true when blitting from and to D32S8 images is supported.
|
||||
bool IsBlitDepth32Stencil8Supported() const {
|
||||
return is_blit_depth32_stencil8_supported;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_NV_viewport_swizzle.
|
||||
@ -488,6 +496,11 @@ public:
|
||||
return extensions.extended_dynamic_state3;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_EXT_4444_formats.
|
||||
bool IsExt4444FormatsSupported() const {
|
||||
return features.format_a4b4g4r4.formatA4B4G4R4;
|
||||
}
|
||||
|
||||
/// Returns true if the device supports VK_EXT_extended_dynamic_state3.
|
||||
bool IsExtExtendedDynamicState3BlendingSupported() const {
|
||||
return dynamic_state3_blending;
|
||||
@ -666,7 +679,7 @@ private:
|
||||
bool ComputeIsOptimalAstcSupported() const;
|
||||
|
||||
/// Returns true if the device natively supports blitting depth stencil images.
|
||||
bool TestDepthStencilBlits() const;
|
||||
bool TestDepthStencilBlits(VkFormat format) const;
|
||||
|
||||
private:
|
||||
VkInstance instance; ///< Vulkan instance.
|
||||
@ -730,25 +743,26 @@ private:
|
||||
VkPhysicalDeviceProperties2 properties2{};
|
||||
|
||||
// Misc features
|
||||
bool is_optimal_astc_supported{}; ///< Support for all guest ASTC formats.
|
||||
bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil.
|
||||
bool is_warp_potentially_bigger{}; ///< Host warp size can be bigger than guest.
|
||||
bool is_integrated{}; ///< Is GPU an iGPU.
|
||||
bool is_virtual{}; ///< Is GPU a virtual GPU.
|
||||
bool is_non_gpu{}; ///< Is SoftwareRasterizer, FPGA, non-GPU device.
|
||||
bool has_broken_compute{}; ///< Compute shaders can cause crashes
|
||||
bool has_broken_cube_compatibility{}; ///< Has broken cube compatibility bit
|
||||
bool has_renderdoc{}; ///< Has RenderDoc attached
|
||||
bool has_nsight_graphics{}; ///< Has Nsight Graphics attached
|
||||
bool supports_d24_depth{}; ///< Supports D24 depth buffers.
|
||||
bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting.
|
||||
bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation
|
||||
bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format.
|
||||
bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3.
|
||||
bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3.
|
||||
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
|
||||
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
|
||||
u32 sets_per_pool{}; ///< Sets per Description Pool
|
||||
bool is_optimal_astc_supported{}; ///< Support for all guest ASTC formats.
|
||||
bool is_blit_depth24_stencil8_supported{}; ///< Support for blitting from and to D24S8.
|
||||
bool is_blit_depth32_stencil8_supported{}; ///< Support for blitting from and to D32S8.
|
||||
bool is_warp_potentially_bigger{}; ///< Host warp size can be bigger than guest.
|
||||
bool is_integrated{}; ///< Is GPU an iGPU.
|
||||
bool is_virtual{}; ///< Is GPU a virtual GPU.
|
||||
bool is_non_gpu{}; ///< Is SoftwareRasterizer, FPGA, non-GPU device.
|
||||
bool has_broken_compute{}; ///< Compute shaders can cause crashes
|
||||
bool has_broken_cube_compatibility{}; ///< Has broken cube compatibility bit
|
||||
bool has_renderdoc{}; ///< Has RenderDoc attached
|
||||
bool has_nsight_graphics{}; ///< Has Nsight Graphics attached
|
||||
bool supports_d24_depth{}; ///< Supports D24 depth buffers.
|
||||
bool cant_blit_msaa{}; ///< Does not support MSAA<->MSAA blitting.
|
||||
bool must_emulate_scaled_formats{}; ///< Requires scaled vertex format emulation
|
||||
bool must_emulate_bgr565{}; ///< Emulates BGR565 by swizzling RGB565 format.
|
||||
bool dynamic_state3_blending{}; ///< Has all blending features of dynamic_state3.
|
||||
bool dynamic_state3_enables{}; ///< Has all enables features of dynamic_state3.
|
||||
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
|
||||
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
|
||||
u32 sets_per_pool{}; ///< Sets per Description Pool
|
||||
|
||||
// Telemetry parameters
|
||||
std::set<std::string, std::less<>> supported_extensions; ///< Reported Vulkan extensions.
|
||||
|
@ -1551,6 +1551,7 @@ void GMainWindow::ConnectMenuEvents() {
|
||||
// Tools
|
||||
connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this,
|
||||
ReinitializeKeyBehavior::Warning));
|
||||
connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
|
||||
connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
|
||||
|
||||
// TAS
|
||||
@ -1590,6 +1591,8 @@ void GMainWindow::UpdateMenuState() {
|
||||
}
|
||||
|
||||
multiplayer_state->UpdateNotificationStatus();
|
||||
|
||||
ui->action_Load_Mii_Edit->setEnabled(CheckFirmwarePresence());
|
||||
}
|
||||
|
||||
void GMainWindow::OnDisplayTitleBars(bool show) {
|
||||
@ -4134,6 +4137,27 @@ void GMainWindow::OnToggleStatusBar() {
|
||||
statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
|
||||
}
|
||||
|
||||
void GMainWindow::OnMiiEdit() {
|
||||
constexpr u64 MiiEditId = 0x0100000000001009ull;
|
||||
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
QMessageBox::warning(this, tr("No firmware available"),
|
||||
tr("Please install the firmware to use the Mii editor."));
|
||||
return;
|
||||
}
|
||||
|
||||
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
|
||||
if (!mii_applet_nca) {
|
||||
QMessageBox::warning(this, tr("Mii Edit Applet"),
|
||||
tr("Mii editor is not available. Please reinstall firmware."));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
|
||||
UISettings::values.roms_path = QFileInfo(filename).path();
|
||||
BootGame(filename);
|
||||
}
|
||||
|
||||
void GMainWindow::OnCaptureScreenshot() {
|
||||
if (emu_thread == nullptr || !emu_thread->IsRunning()) {
|
||||
return;
|
||||
@ -4540,6 +4564,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
|
||||
if (behavior == ReinitializeKeyBehavior::Warning) {
|
||||
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||
}
|
||||
|
||||
UpdateMenuState();
|
||||
}
|
||||
|
||||
bool GMainWindow::CheckSystemArchiveDecryption() {
|
||||
@ -4561,6 +4587,22 @@ bool GMainWindow::CheckSystemArchiveDecryption() {
|
||||
return mii_nca->GetRomFS().get() != nullptr;
|
||||
}
|
||||
|
||||
bool GMainWindow::CheckFirmwarePresence() {
|
||||
constexpr u64 MiiEditId = 0x0100000000001009ull;
|
||||
|
||||
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
|
||||
if (!mii_applet_nca) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
|
||||
u64* selected_title_id, u8* selected_content_record_type) {
|
||||
using ContentInfo = std::pair<FileSys::TitleType, FileSys::ContentRecordType>;
|
||||
|
@ -365,6 +365,7 @@ private slots:
|
||||
void ResetWindowSize720();
|
||||
void ResetWindowSize900();
|
||||
void ResetWindowSize1080();
|
||||
void OnMiiEdit();
|
||||
void OnCaptureScreenshot();
|
||||
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
|
||||
void OnLanguageChanged(const QString& locale);
|
||||
@ -409,6 +410,7 @@ private:
|
||||
void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);
|
||||
bool CheckDarkMode();
|
||||
bool CheckSystemArchiveDecryption();
|
||||
bool CheckFirmwarePresence();
|
||||
void ConfigureFilesystemProvider(const std::string& filepath);
|
||||
|
||||
QString GetTasStateDescription() const;
|
||||
|
@ -150,6 +150,8 @@
|
||||
<addaction name="action_Rederive"/>
|
||||
<addaction name="action_Verify_installed_contents"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Load_Mii_Edit"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Capture_Screenshot"/>
|
||||
<addaction name="menuTAS"/>
|
||||
</widget>
|
||||
@ -217,7 +219,7 @@
|
||||
</action>
|
||||
<action name="action_Verify_installed_contents">
|
||||
<property name="text">
|
||||
<string>Verify installed contents</string>
|
||||
<string>&Verify Installed Contents</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_About">
|
||||
@ -368,6 +370,11 @@
|
||||
<string>&Capture Screenshot</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Mii_Edit">
|
||||
<property name="text">
|
||||
<string>Open &Mii Editor</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Configure_Tas">
|
||||
<property name="text">
|
||||
<string>&Configure TAS...</string>
|
||||
|
Reference in New Issue
Block a user