Compare commits
3 Commits
android-22
...
android-21
Author | SHA1 | Date | |
---|---|---|---|
028ddd9297 | |||
2588c74fb5 | |||
cb5c1bab01 |
@ -322,10 +322,6 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
|||||||
find_package(xbyak 6 CONFIG)
|
find_package(xbyak 6 CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ARCHITECTURE_arm64)
|
|
||||||
find_package(oaknut 2.0.1 CONFIG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||||
find_package(dynarmic 6.4.0 CONFIG)
|
find_package(dynarmic 6.4.0 CONFIG)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
| Pull Request | Commit | Title | Author | Merged? |
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|----|----|----|----|----|
|
|----|----|----|----|----|
|
||||||
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e644610e1`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`8e0a40434`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`a407f9bf5`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||||
|
|
||||||
|
|
||||||
End of merge log. You can find the original README.md below the break.
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
5
externals/CMakeLists.txt
vendored
5
externals/CMakeLists.txt
vendored
@ -14,17 +14,16 @@ set(BUILD_SHARED_LIBS OFF)
|
|||||||
# Skip install rules for all externals
|
# Skip install rules for all externals
|
||||||
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||||
|
|
||||||
# Xbyak (also used by Dynarmic, so needs to be added first)
|
# xbyak
|
||||||
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
||||||
add_subdirectory(xbyak)
|
add_subdirectory(xbyak)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Oaknut (also used by Dynarmic, so needs to be added first)
|
# Dynarmic
|
||||||
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
|
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
|
||||||
add_subdirectory(oaknut)
|
add_subdirectory(oaknut)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Dynarmic
|
|
||||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
||||||
set(DYNARMIC_IGNORE_ASSERTS ON)
|
set(DYNARMIC_IGNORE_ASSERTS ON)
|
||||||
add_subdirectory(dynarmic)
|
add_subdirectory(dynarmic)
|
||||||
|
@ -261,7 +261,7 @@ object NativeLibrary {
|
|||||||
/**
|
/**
|
||||||
* Begins emulation.
|
* Begins emulation.
|
||||||
*/
|
*/
|
||||||
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
|
external fun run(path: String?, programIndex: Int = 0)
|
||||||
|
|
||||||
// Surface Handling
|
// Surface Handling
|
||||||
external fun surfaceChanged(surf: Surface?)
|
external fun surfaceChanged(surf: Surface?)
|
||||||
|
@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
emulationThread.join()
|
emulationThread.join()
|
||||||
emulationThread = Thread({
|
emulationThread = Thread({
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
NativeLibrary.run(gamePath, programIndex, false)
|
NativeLibrary.run(gamePath, programIndex)
|
||||||
}, "NativeEmulation")
|
}, "NativeEmulation")
|
||||||
emulationThread.start()
|
emulationThread.start()
|
||||||
}
|
}
|
||||||
@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
State.STOPPED -> {
|
State.STOPPED -> {
|
||||||
emulationThread = Thread({
|
emulationThread = Thread({
|
||||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||||
NativeLibrary.run(gamePath, programIndex, true)
|
NativeLibrary.run(gamePath, programIndex)
|
||||||
}, "NativeEmulation")
|
}, "NativeEmulation")
|
||||||
emulationThread.start()
|
emulationThread.start()
|
||||||
}
|
}
|
||||||
|
@ -219,8 +219,7 @@ void EmulationSession::SetAppletId(int applet_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
||||||
const std::size_t program_index,
|
const std::size_t program_index) {
|
||||||
const bool frontend_initiated) {
|
|
||||||
std::scoped_lock lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
// Create the render window.
|
// Create the render window.
|
||||||
@ -252,8 +251,6 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
|||||||
// Load the ROM.
|
// Load the ROM.
|
||||||
Service::AM::FrontendAppletParameters params{
|
Service::AM::FrontendAppletParameters params{
|
||||||
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
||||||
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
|
|
||||||
: Service::AM::LaunchType::ApplicationInitiated,
|
|
||||||
.program_index = static_cast<s32>(program_index),
|
.program_index = static_cast<s32>(program_index),
|
||||||
};
|
};
|
||||||
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
||||||
@ -450,8 +447,7 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||||
const size_t program_index,
|
const size_t program_index = 0) {
|
||||||
const bool frontend_initiated) {
|
|
||||||
MicroProfileOnThreadCreate("EmuThread");
|
MicroProfileOnThreadCreate("EmuThread");
|
||||||
SCOPE_EXIT({ MicroProfileShutdown(); });
|
SCOPE_EXIT({ MicroProfileShutdown(); });
|
||||||
|
|
||||||
@ -464,8 +460,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
|||||||
|
|
||||||
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
||||||
|
|
||||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
|
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
|
||||||
frontend_initiated);
|
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -762,12 +757,10 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
||||||
jint j_program_index,
|
jint j_program_index) {
|
||||||
jboolean j_frontend_initiated) {
|
|
||||||
const std::string path = GetJString(env, j_path);
|
const std::string path = GetJString(env, j_path);
|
||||||
|
|
||||||
const Core::SystemResultStatus result{
|
const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
|
||||||
RunEmulation(path, j_program_index, j_frontend_initiated)};
|
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
if (result != Core::SystemResultStatus::Success) {
|
||||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||||
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
||||||
|
@ -47,8 +47,7 @@ public:
|
|||||||
void InitializeSystem(bool reload);
|
void InitializeSystem(bool reload);
|
||||||
void SetAppletId(int applet_id);
|
void SetAppletId(int applet_id);
|
||||||
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
||||||
const std::size_t program_index,
|
const std::size_t program_index = 0);
|
||||||
const bool frontend_initiated);
|
|
||||||
|
|
||||||
bool IsHandheldOnly();
|
bool IsHandheldOnly();
|
||||||
void SetDeviceType([[maybe_unused]] int index, int type);
|
void SetDeviceType([[maybe_unused]] int index, int type);
|
||||||
|
@ -122,14 +122,14 @@ struct RequestLayout {
|
|||||||
u32 domain_interface_count;
|
u32 domain_interface_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
template <ArgumentType Type1, ArgumentType Type2, typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||||
constexpr u32 GetInRawDataSize() {
|
constexpr u32 GetArgumentRawDataSize() {
|
||||||
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
||||||
return static_cast<u32>(DataOffset);
|
return static_cast<u32>(DataOffset);
|
||||||
} else {
|
} else {
|
||||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||||
|
|
||||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InData || ArgumentTraits<ArgType>::Type == ArgumentType::InProcessId) {
|
if constexpr (ArgumentTraits<ArgType>::Type == Type1 || ArgumentTraits<ArgType>::Type == Type2) {
|
||||||
constexpr size_t ArgAlign = alignof(ArgType);
|
constexpr size_t ArgAlign = alignof(ArgType);
|
||||||
constexpr size_t ArgSize = sizeof(ArgType);
|
constexpr size_t ArgSize = sizeof(ArgType);
|
||||||
|
|
||||||
@ -138,33 +138,9 @@ constexpr u32 GetInRawDataSize() {
|
|||||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||||
|
|
||||||
return GetInRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||||
} else {
|
} else {
|
||||||
return GetInRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
|
||||||
constexpr u32 GetOutRawDataSize() {
|
|
||||||
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
|
||||||
return static_cast<u32>(DataOffset);
|
|
||||||
} else {
|
|
||||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
|
||||||
|
|
||||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
|
||||||
using RawArgType = typename ArgType::Type;
|
|
||||||
constexpr size_t ArgAlign = alignof(RawArgType);
|
|
||||||
constexpr size_t ArgSize = sizeof(RawArgType);
|
|
||||||
|
|
||||||
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
|
||||||
|
|
||||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
|
||||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
|
||||||
|
|
||||||
return GetOutRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
|
||||||
} else {
|
|
||||||
return GetOutRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,7 +165,7 @@ constexpr RequestLayout GetNonDomainReplyInLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = 0,
|
.move_handle_count = 0,
|
||||||
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
||||||
.domain_interface_count = 0,
|
.domain_interface_count = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -199,7 +175,7 @@ constexpr RequestLayout GetDomainReplyInLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = 0,
|
.move_handle_count = 0,
|
||||||
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
||||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(),
|
.domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -209,7 +185,7 @@ constexpr RequestLayout GetNonDomainReplyOutLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||||
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
||||||
.domain_interface_count = 0,
|
.domain_interface_count = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -219,7 +195,7 @@ constexpr RequestLayout GetDomainReplyOutLayout() {
|
|||||||
return RequestLayout{
|
return RequestLayout{
|
||||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(),
|
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(),
|
||||||
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
||||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
.domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -283,7 +259,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
|||||||
|
|
||||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
constexpr size_t BufferSize = sizeof(ArgType);
|
||||||
|
|
||||||
// Clear the existing data.
|
// Clear the existing data.
|
||||||
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
||||||
@ -324,7 +300,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
|||||||
|
|
||||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
constexpr size_t BufferSize = sizeof(ArgType);
|
||||||
|
|
||||||
// Clear the existing data.
|
// Clear the existing data.
|
||||||
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
|
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
|
||||||
@ -361,15 +337,13 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
|
|||||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||||
|
|
||||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
||||||
using RawArgType = decltype(std::get<ArgIndex>(args).raw);
|
constexpr size_t ArgAlign = alignof(ArgType);
|
||||||
constexpr size_t ArgAlign = alignof(RawArgType);
|
constexpr size_t ArgSize = sizeof(ArgType);
|
||||||
constexpr size_t ArgSize = sizeof(RawArgType);
|
|
||||||
|
|
||||||
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
||||||
static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
|
static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
|
||||||
static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
|
static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
|
||||||
static_assert(!std::is_pointer_v<RawArgType>, "Output raw data must not be a pointer");
|
static_assert(std::is_trivially_copyable_v<decltype(std::get<ArgIndex>(args).raw)>, "Output raw data must be trivially copyable");
|
||||||
static_assert(std::is_trivially_copyable_v<RawArgType>, "Output raw data must be trivially copyable");
|
|
||||||
|
|
||||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||||
@ -394,7 +368,7 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
|
|||||||
|
|
||||||
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
constexpr size_t BufferSize = sizeof(ArgType);
|
||||||
|
|
||||||
ASSERT(ctx.CanWriteBuffer(OutBufferIndex));
|
ASSERT(ctx.CanWriteBuffer(OutBufferIndex));
|
||||||
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
|
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include "core/hle/kernel/k_shared_memory.h"
|
#include "core/hle/kernel/k_shared_memory.h"
|
||||||
#include "core/hle/kernel/k_transfer_memory.h"
|
#include "core/hle/kernel/k_transfer_memory.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
|
||||||
#include "core/hle/service/hid/hid_server.h"
|
#include "core/hle/service/hid/hid_server.h"
|
||||||
#include "core/hle/service/ipc_helpers.h"
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
@ -154,7 +153,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r
|
|||||||
{104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
|
{104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
|
||||||
{106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
|
{106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
|
||||||
{107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
|
{107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
|
||||||
{108, C<&IHidServer::GetPlayerLedPattern>, "GetPlayerLedPattern"},
|
{108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"},
|
||||||
{109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
|
{109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
|
||||||
{120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
|
{120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
|
||||||
{121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
|
{121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
|
||||||
@ -1137,39 +1136,19 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
|
|||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
|
||||||
Core::HID::NpadIdType npad_id) {
|
IPC::RequestParser rp{ctx};
|
||||||
|
const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
|
||||||
|
|
||||||
|
Core::HID::LedPattern pattern{0, 0, 0, 0};
|
||||||
|
auto controller = GetResourceManager()->GetNpad();
|
||||||
|
const auto result = controller->GetLedPattern(npad_id, pattern);
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
|
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
|
||||||
|
|
||||||
switch (npad_id) {
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
case Core::HID::NpadIdType::Player1:
|
rb.Push(result);
|
||||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 0};
|
rb.Push(pattern.raw);
|
||||||
R_SUCCEED();
|
|
||||||
case Core::HID::NpadIdType::Player2:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 0, 0};
|
|
||||||
R_SUCCEED();
|
|
||||||
case Core::HID::NpadIdType::Player3:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 0};
|
|
||||||
R_SUCCEED();
|
|
||||||
case Core::HID::NpadIdType::Player4:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 1};
|
|
||||||
R_SUCCEED();
|
|
||||||
case Core::HID::NpadIdType::Player5:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 1};
|
|
||||||
R_SUCCEED();
|
|
||||||
case Core::HID::NpadIdType::Player6:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 0};
|
|
||||||
R_SUCCEED();
|
|
||||||
case Core::HID::NpadIdType::Player7:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 1};
|
|
||||||
R_SUCCEED();
|
|
||||||
case Core::HID::NpadIdType::Player8:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{0, 1, 1, 0};
|
|
||||||
R_SUCCEED();
|
|
||||||
default:
|
|
||||||
*out_led_pattern = Core::HID::LedPattern{0, 0, 0, 0};
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/cmif_types.h"
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "hid_core/hid_types.h"
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
@ -68,8 +66,7 @@ private:
|
|||||||
void DeactivateNpad(HLERequestContext& ctx);
|
void DeactivateNpad(HLERequestContext& ctx);
|
||||||
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
||||||
void DisconnectNpad(HLERequestContext& ctx);
|
void DisconnectNpad(HLERequestContext& ctx);
|
||||||
Result GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
void GetPlayerLedPattern(HLERequestContext& ctx);
|
||||||
Core::HID::NpadIdType npad_id);
|
|
||||||
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
||||||
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
||||||
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
||||||
|
@ -83,9 +83,7 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
|
|||||||
|
|
||||||
// Check if this memory block is heap.
|
// Check if this memory block is heap.
|
||||||
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
|
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
|
||||||
if (region_start + region_size == svc_mem_info.base_address) {
|
if (svc_mem_info.size > region_size) {
|
||||||
region_size += svc_mem_info.size;
|
|
||||||
} else if (svc_mem_info.size > region_size) {
|
|
||||||
region_size = svc_mem_info.size;
|
region_size = svc_mem_info.size;
|
||||||
region_start = svc_mem_info.base_address;
|
region_start = svc_mem_info.base_address;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ enum class Errno : u32 {
|
|||||||
CONNRESET = 104,
|
CONNRESET = 104,
|
||||||
NOTCONN = 107,
|
NOTCONN = 107,
|
||||||
TIMEDOUT = 110,
|
TIMEDOUT = 110,
|
||||||
CONNREFUSED = 111,
|
|
||||||
INPROGRESS = 115,
|
INPROGRESS = 115,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,8 +25,6 @@ Errno Translate(Network::Errno value) {
|
|||||||
return Errno::MFILE;
|
return Errno::MFILE;
|
||||||
case Network::Errno::PIPE:
|
case Network::Errno::PIPE:
|
||||||
return Errno::PIPE;
|
return Errno::PIPE;
|
||||||
case Network::Errno::CONNREFUSED:
|
|
||||||
return Errno::CONNREFUSED;
|
|
||||||
case Network::Errno::NOTCONN:
|
case Network::Errno::NOTCONN:
|
||||||
return Errno::NOTCONN;
|
return Errno::NOTCONN;
|
||||||
case Network::Errno::TIMEDOUT:
|
case Network::Errno::TIMEDOUT:
|
||||||
|
@ -422,10 +422,7 @@ struct NpadPowerInfo {
|
|||||||
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
|
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
|
||||||
|
|
||||||
struct LedPattern {
|
struct LedPattern {
|
||||||
LedPattern() {
|
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
||||||
raw = 0;
|
|
||||||
}
|
|
||||||
LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
|
||||||
position1.Assign(light1);
|
position1.Assign(light1);
|
||||||
position2.Assign(light2);
|
position2.Assign(light2);
|
||||||
position3.Assign(light3);
|
position3.Assign(light3);
|
||||||
|
@ -956,6 +956,17 @@ Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1,
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
|
||||||
|
if (!IsNpadIdValid(npad_id)) {
|
||||||
|
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
|
||||||
|
return ResultInvalidNpadId;
|
||||||
|
}
|
||||||
|
const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
|
||||||
|
const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device;
|
||||||
|
pattern = controller->GetLedPattern();
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
||||||
Core::HID::NpadIdType npad_id) const {
|
Core::HID::NpadIdType npad_id) const {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
@ -97,6 +97,8 @@ public:
|
|||||||
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
|
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
|
||||||
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle);
|
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle);
|
||||||
|
|
||||||
|
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
|
||||||
|
|
||||||
Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
||||||
Core::HID::NpadIdType npad_id) const;
|
Core::HID::NpadIdType npad_id) const;
|
||||||
Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id,
|
Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id,
|
||||||
|
@ -1431,8 +1431,7 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ForEachSparseImageInRegion(channel_state->gpu_memory.GetID(), gpu_addr, size_bytes,
|
ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu);
|
||||||
region_check_gpu);
|
|
||||||
|
|
||||||
bool can_rescale = info.rescaleable;
|
bool can_rescale = info.rescaleable;
|
||||||
bool any_rescaled = false;
|
bool any_rescaled = false;
|
||||||
@ -1843,7 +1842,7 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
|
|||||||
if (!storage_id) {
|
if (!storage_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& gpu_page_table = gpu_page_table_storage[*storage_id * 2];
|
auto& gpu_page_table = gpu_page_table_storage[*storage_id];
|
||||||
ForEachGPUPage(gpu_addr, size,
|
ForEachGPUPage(gpu_addr, size,
|
||||||
[this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) {
|
[this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) {
|
||||||
const auto it = gpu_page_table.find(page);
|
const auto it = gpu_page_table.find(page);
|
||||||
@ -1883,18 +1882,11 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
|
|||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void TextureCache<P>::ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size,
|
void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func) {
|
||||||
Func&& func) {
|
|
||||||
using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type;
|
using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type;
|
||||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||||
boost::container::small_vector<ImageId, 8> images;
|
boost::container::small_vector<ImageId, 8> images;
|
||||||
auto storage_id = getStorageID(as_id);
|
ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) {
|
||||||
if (!storage_id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto& sparse_page_table = gpu_page_table_storage[*storage_id * 2 + 1];
|
|
||||||
ForEachGPUPage(gpu_addr, size,
|
|
||||||
[this, &sparse_page_table, &images, gpu_addr, size, func](u64 page) {
|
|
||||||
const auto it = sparse_page_table.find(page);
|
const auto it = sparse_page_table.find(page);
|
||||||
if (it == sparse_page_table.end()) {
|
if (it == sparse_page_table.end()) {
|
||||||
if constexpr (BOOL_BREAK) {
|
if constexpr (BOOL_BREAK) {
|
||||||
@ -1996,9 +1988,8 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
|
|||||||
sparse_maps.push_back(map_id);
|
sparse_maps.push_back(map_id);
|
||||||
});
|
});
|
||||||
sparse_views.emplace(image_id, std::move(sparse_maps));
|
sparse_views.emplace(image_id, std::move(sparse_maps));
|
||||||
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) {
|
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
|
||||||
(*channel_state->sparse_page_table)[page].push_back(image_id);
|
[this, image_id](u64 page) { sparse_page_table[page].push_back(image_id); });
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
@ -2051,7 +2042,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) {
|
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) {
|
||||||
clear_page_table(page, (*channel_state->sparse_page_table));
|
clear_page_table(page, sparse_page_table);
|
||||||
});
|
});
|
||||||
auto it = sparse_views.find(image_id);
|
auto it = sparse_views.find(image_id);
|
||||||
ASSERT(it != sparse_views.end());
|
ASSERT(it != sparse_views.end());
|
||||||
@ -2505,15 +2496,13 @@ void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel
|
|||||||
const auto it = channel_map.find(channel.bind_id);
|
const auto it = channel_map.find(channel.bind_id);
|
||||||
auto* this_state = &channel_storage[it->second];
|
auto* this_state = &channel_storage[it->second];
|
||||||
const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()];
|
const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()];
|
||||||
this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2];
|
this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id];
|
||||||
this_state->sparse_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2 + 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bind a channel for execution.
|
/// Bind a channel for execution.
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) {
|
void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) {
|
||||||
gpu_page_table_storage.emplace_back();
|
gpu_page_table_storage.emplace_back();
|
||||||
gpu_page_table_storage.emplace_back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VideoCommon
|
} // namespace VideoCommon
|
||||||
|
@ -86,7 +86,6 @@ public:
|
|||||||
std::unordered_map<TSCEntry, SamplerId> samplers;
|
std::unordered_map<TSCEntry, SamplerId> samplers;
|
||||||
|
|
||||||
TextureCacheGPUMap* gpu_page_table;
|
TextureCacheGPUMap* gpu_page_table;
|
||||||
TextureCacheGPUMap* sparse_page_table;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
@ -358,7 +357,7 @@ private:
|
|||||||
void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
||||||
|
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
void ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func);
|
||||||
|
|
||||||
/// Iterates over all the images in a region calling func
|
/// Iterates over all the images in a region calling func
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
@ -432,6 +431,7 @@ private:
|
|||||||
std::unordered_map<RenderTargets, FramebufferId> framebuffers;
|
std::unordered_map<RenderTargets, FramebufferId> framebuffers;
|
||||||
|
|
||||||
std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
|
std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
|
||||||
|
std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table;
|
||||||
std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views;
|
std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views;
|
||||||
|
|
||||||
DAddr virtual_invalid_space{};
|
DAddr virtual_invalid_space{};
|
||||||
|
Reference in New Issue
Block a user